@@ -102,7 +102,7 @@ defmodule Oban.Peers.Database do
102
102
fun = fn ->
103
103
state
104
104
|> delete_expired_peers ( )
105
- |> upsert_peer ( )
105
+ |> attempt_leadership ( )
106
106
end
107
107
108
108
case Repo . transaction ( state . conf , fun , retry: 1 ) do
@@ -163,14 +163,7 @@ defmodule Oban.Peers.Database do
163
163
end
164
164
165
165
def handle_call ( :get_leader , _from , % State { conf: conf } = state ) do
166
- query =
167
- "oban_peers"
168
- |> where ( [ p ] , p . name == ^ inspect ( conf . name ) )
169
- |> select ( [ p ] , p . node )
170
-
171
- leader = Repo . one ( conf , query )
172
-
173
- { :reply , leader , state }
166
+ { :reply , query_leader ( conf ) , state }
174
167
end
175
168
176
169
# Helpers
@@ -199,11 +192,16 @@ defmodule Oban.Peers.Database do
199
192
Repo . delete_all ( conf , query )
200
193
end
201
194
202
- defp notify_down ( % State { conf: conf } ) do
203
- Notifier . notify ( conf , :leader , % { down: inspect ( conf . name ) } )
195
+ defp query_leader ( conf ) do
196
+ query =
197
+ "oban_peers"
198
+ |> where ( [ p ] , p . name == ^ inspect ( conf . name ) )
199
+ |> select ( [ p ] , p . node )
200
+
201
+ Repo . one ( conf , query )
204
202
end
205
203
206
- defp upsert_peer ( % State { conf: conf } = state ) do
204
+ defp attempt_leadership ( % State { conf: conf } = state ) do
207
205
started_at = DateTime . utc_now ( )
208
206
expires_at = DateTime . add ( started_at , state . interval , :millisecond )
209
207
@@ -214,24 +212,46 @@ defmodule Oban.Peers.Database do
214
212
expires_at: expires_at
215
213
}
216
214
217
- # MySQL only supports auto-inference and not conflict_target.
218
- base_opts =
215
+ leader? =
219
216
if state . conf . engine == Oban.Engines.Dolphin do
220
- [ ]
217
+ dolphin_insert ( peer_data , state )
221
218
else
222
- [ conflict_target: :name ]
219
+ regular_upsert ( peer_data , state )
223
220
end
224
221
222
+ % { state | leader?: leader? }
223
+ end
224
+
225
+ defp regular_upsert ( peer_data , state ) do
225
226
repo_opts =
226
227
if state . leader? do
227
- Keyword . put ( base_opts , :on_conflict , set: [ expires_at: expires_at ] )
228
+ [ conflict_target: :name , on_conflict: [ set: [ expires_at: peer_data . expires_at ] ] ]
228
229
else
229
- [ on_conflict: :nothing ]
230
+ [ conflict_target: :name , on_conflict: :nothing ]
230
231
end
231
232
232
- case Repo . insert_all ( conf , "oban_peers" , [ peer_data ] , repo_opts ) do
233
- { 0 , nil } -> % { state | leader?: false }
234
- { _ , nil } -> % { state | leader?: true }
233
+ case Repo . insert_all ( state . conf , "oban_peers" , [ peer_data ] , repo_opts ) do
234
+ { 0 , nil } -> false
235
+ { _ , nil } -> true
235
236
end
236
237
end
238
+
239
+ defp dolphin_insert ( peer_data , state ) do
240
+ repo_opts =
241
+ if state . leader? do
242
+ [ on_conflict: [ set: [ expires_at: peer_data . expires_at ] ] ]
243
+ else
244
+ [ on_conflict: :nothing ]
245
+ end
246
+
247
+ # MySQL always returns the number of entries attempted, even when nothing was added. We have
248
+ # to check the leader after update.
249
+ Repo . insert_all ( state . conf , "oban_peers" , [ peer_data ] , repo_opts )
250
+
251
+ query_leader ( state . conf ) == peer_data . node
252
+ end
253
+
254
+ defp notify_down ( % State { conf: conf } ) do
255
+ Notifier . notify ( conf , :leader , % { down: inspect ( conf . name ) } )
256
+ end
237
257
end
0 commit comments