@@ -10,8 +10,16 @@ module RefreshingIdentityProvider
1010 SYNC_EXPIRATION_LENGTH = 300 # 5 minutes
1111 ASYNC_EXPIRATION_LENGTH = 600 # 10 minutes
1212
13- def initialize ( _options = { } )
13+ CLIENT_EXCLUDE_OPTIONS = Set . new ( [ :before_refresh ] ) . freeze
14+
15+ # @param [Hash] options
16+ # @option options [Proc] :before_refresh A Proc called before credentials are refreshed.
17+ # It accepts `self` as the only argument.
18+ def initialize ( options = { } )
1419 @mutex = Mutex . new
20+ @before_refresh = options . delete ( :before_refresh ) if options . is_a? ( Hash )
21+
22+ @before_refresh &.call ( self )
1523 refresh
1624 end
1725
@@ -24,7 +32,11 @@ def identity
2432 # Refresh credentials.
2533 # @return [void]
2634 def refresh!
27- @mutex . synchronize { refresh }
35+ @mutex . synchronize do
36+ @before_refresh &.call ( self )
37+
38+ refresh
39+ end
2840 end
2941
3042 private
@@ -46,15 +58,29 @@ def refresh_if_near_expiration!
4658 # every #refresh_if_near_expiration call, we check before doing so, and
4759 # then we check within the mutex to avoid a race condition.
4860 if near_expiration? ( sync_expiration_length )
49- @mutex . synchronize do
50- refresh if near_expiration? ( sync_expiration_length )
51- end
61+ sync_refresh
5262 elsif @async_refresh && near_expiration? ( async_expiration_length )
53- unless @mutex . locked?
54- Thread . new do
55- @mutex . synchronize do
56- refresh if near_expiration? ( async_expiration_length )
57- end
63+ async_refresh
64+ end
65+ end
66+
67+ def sync_refresh
68+ @mutex . synchronize do
69+ if near_expiration? ( sync_expiration_length )
70+ @before_refresh &.call ( self )
71+ refresh
72+ end
73+ end
74+ end
75+
76+ def async_refresh
77+ return if @mutex . locked?
78+
79+ Thread . new do
80+ @mutex . synchronize do
81+ if near_expiration? ( async_expiration_length )
82+ @before_refresh &.call ( self )
83+ refresh
5884 end
5985 end
6086 end
0 commit comments