@@ -56,7 +56,8 @@ defmodule DBConnection.Ownership.Manager do
5656 :ok | { :already , :owner | :allowed } | :not_found
5757 def allow ( manager , parent , allow , opts ) do
5858 timeout = Keyword . get ( opts , :timeout , @ timeout )
59- GenServer . call ( manager , { :allow , parent , allow } , timeout )
59+ passed_opts = Keyword . take ( opts , [ :unallow_existing ] )
60+ GenServer . call ( manager , { :allow , parent , allow , passed_opts } , timeout )
6061 end
6162
6263 @ spec get_connection_metrics ( GenServer . server ( ) ) ::
@@ -170,15 +171,24 @@ defmodule DBConnection.Ownership.Manager do
170171 { :reply , reply , state }
171172 end
172173
173- def handle_call ( { :allow , caller , allow } , _from , % { checkouts: checkouts } = state ) do
174- if kind = already_checked_out ( checkouts , allow ) do
174+ def handle_call ( { :allow , caller , allow , opts } , _from , % { checkouts: checkouts } = state ) do
175+ unallow_existing = Keyword . get ( opts , :unallow_existing , false )
176+ kind = already_checked_out ( checkouts , allow )
177+
178+ if ! unallow_existing && kind do
175179 { :reply , { :already , kind } , state }
176180 else
177181 case Map . get ( checkouts , caller , :not_found ) do
178182 { :owner , ref , proxy } ->
183+ state =
184+ if unallow_existing , do: owner_unallow ( state , caller , allow , ref , proxy ) , else: state
185+
179186 { :reply , :ok , owner_allow ( state , caller , allow , ref , proxy ) }
180187
181188 { :allowed , ref , proxy } ->
189+ state =
190+ if unallow_existing , do: owner_unallow ( state , caller , allow , ref , proxy ) , else: state
191+
182192 { :reply , :ok , owner_allow ( state , caller , allow , ref , proxy ) }
183193
184194 :not_found ->
@@ -310,6 +320,24 @@ defmodule DBConnection.Ownership.Manager do
310320 state
311321 end
312322
323+ defp owner_unallow ( % { ets: ets , log: log } = state , caller , unallow , ref , proxy ) do
324+ if log do
325+ Logger . log ( log , fn ->
326+ [ inspect ( unallow ) , " was unallowed by " , inspect ( caller ) , " on proxy " , inspect ( proxy ) ]
327+ end )
328+ end
329+
330+ state = update_in ( state . checkouts , & Map . delete ( & 1 , unallow ) )
331+
332+ state =
333+ update_in ( state . owners [ ref ] , fn { proxy , caller , allowed } ->
334+ { proxy , caller , List . delete ( allowed , unallow ) }
335+ end )
336+
337+ ets && :ets . delete ( ets , { unallow , proxy } )
338+ state
339+ end
340+
313341 defp owner_down ( % { ets: ets , log: log } = state , ref ) do
314342 case get_and_update_in ( state . owners , & Map . pop ( & 1 , ref ) ) do
315343 { { proxy , caller , allowed } , state } ->
0 commit comments