@@ -42,7 +42,8 @@ import PostgresNIO
42
42
/// try await migrations.apply(client: postgresClient, logger: logger, dryRun: applyMigrations)
43
43
/// }
44
44
/// ```
45
- public final class PostgresJobQueue : JobQueueDriver {
45
+ public final class PostgresJobQueue : JobQueueDriver , CancellableJobQueueProtocol , ResumeableJobQueueProtocol {
46
+
46
47
public typealias JobID = UUID
47
48
/// what to do with failed/processing jobs from last time queue was handled
48
49
public enum JobCleanup : Sendable {
@@ -131,6 +132,8 @@ public final class PostgresJobQueue: JobQueueDriver {
131
132
case pending = 0
132
133
case processing = 1
133
134
case failed = 2
135
+ case cancelled = 3
136
+ case paused = 4
134
137
}
135
138
136
139
/// Queue configuration
@@ -171,7 +174,7 @@ public final class PostgresJobQueue: JobQueueDriver {
171
174
self . logger = logger
172
175
self . isStopped = . init( false )
173
176
self . migrations = migrations
174
- await migrations. add ( CreateSwiftJobsMigrations ( ) )
177
+ await migrations. add ( CreateSwiftJobsMigrations ( ) , checkForDuplicates : true )
175
178
}
176
179
177
180
public func onInit( ) async throws {
@@ -180,6 +183,56 @@ public final class PostgresJobQueue: JobQueueDriver {
180
183
try await self . migrations. waitUntilCompleted ( )
181
184
}
182
185
186
+ /// Cancel job
187
+ ///
188
+ /// This function is used to cancel a job. Job cancellation is not gaurenteed howerever.
189
+ /// Cancellable jobs are jobs with a delayed greather than when the cancellation request was made
190
+ ///
191
+ /// - Parameters:
192
+ /// - jobID: an existing job
193
+ /// - Throws:
194
+ public func cancel( jobID: JobID ) async throws {
195
+ try await self . client. withTransaction ( logger: logger) { connection in
196
+ try await deleteFromQueue ( jobID: jobID, connection: connection)
197
+ try await setStatus ( jobID: jobID, status: . cancelled, connection: connection)
198
+ }
199
+ }
200
+
201
+ /// Pause job
202
+ ///
203
+ /// This function is used to pause a job. Job paus is not gaurenteed howerever.
204
+ /// Pausable jobs are jobs with a delayed greather than when the pause request was made
205
+ ///
206
+ /// - Parameters:
207
+ /// - jobID: an existing job
208
+ /// - Throws:
209
+ public func pause( jobID: UUID ) async throws {
210
+ try await self . client. withTransaction ( logger: logger) { connection in
211
+ try await deleteFromQueue ( jobID: jobID, connection: connection)
212
+ try await setStatus ( jobID: jobID, status: . paused, connection: connection)
213
+ }
214
+ }
215
+
216
+ /// Resume job
217
+ ///
218
+ /// This function is used to resume jobs. Job is not gaurenteed howerever.
219
+ /// Cancellable jobs are jobs with a delayed greather than when the cancellation request was made
220
+ ///
221
+ /// - Parameters:
222
+ /// - jobID: an existing job
223
+ /// - Throws:
224
+ public func resume( jobID: JobID ) async throws {
225
+ try await self . client. withTransaction ( logger: logger) { connection in
226
+ try await setStatus ( jobID: jobID, status: . pending, connection: connection)
227
+ try await addToQueue (
228
+ jobID: jobID,
229
+ queueName: configuration. queueName,
230
+ options: . init( ) ,
231
+ connection: connection
232
+ )
233
+ }
234
+ }
235
+
183
236
/// Cleanup job queues
184
237
///
185
238
/// This function is used to re-run or delete jobs in a certain state. Failed jobs can be
@@ -431,6 +484,16 @@ public final class PostgresJobQueue: JobQueueDriver {
431
484
logger: self . logger
432
485
)
433
486
}
487
+
488
+ func deleteFromQueue( jobID: JobID , connection: PostgresConnection ) async throws {
489
+ try await connection. query (
490
+ """
491
+ DELETE FROM swift_jobs.queues
492
+ WHERE job_id = \( jobID) AND queue_name = \( configuration. queueName)
493
+ """ ,
494
+ logger: self . logger
495
+ )
496
+ }
434
497
435
498
func addToQueue( jobID: JobID , queueName: String , options: JobOptions , connection: PostgresConnection ) async throws {
436
499
try await connection. query (
0 commit comments