From f1bcf9cd9d3418feb3ec89cf253ab37e4d97ddb1 Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Thu, 1 Feb 2024 13:54:41 -0600 Subject: [PATCH] Some general cleanup --- .github/CODEOWNERS | 1 + Package@swift-5.9.swift | 17 +++++----- Sources/QueuesFluentDriver/FluentQueue.swift | 2 +- .../QueuesFluentDriver/SQLSkipLocked.swift | 32 +++++++++++-------- 4 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..bfbc683 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @gwynne diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift index 72b42e6..1e42ebb 100644 --- a/Package@swift-5.9.swift +++ b/Package@swift-5.9.swift @@ -1,14 +1,6 @@ // swift-tools-version:5.9 import PackageDescription -let swiftSettings: [SwiftSetting] = [ - .enableUpcomingFeature("ForwardTrailingClosures"), - .enableUpcomingFeature("ExistentialAny"), - .enableUpcomingFeature("ConciseMagicFile"), - .enableUpcomingFeature("DisableOutwardActorInference"), - .enableExperimentalFeature("StrictConcurrency=complete"), -] - let package = Package( name: "QueuesFluentDriver", platforms: [ @@ -49,3 +41,12 @@ let package = Package( ), ] ) + +var swiftSettings: [SwiftSetting] { [ + .enableUpcomingFeature("ForwardTrailingClosures"), + .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("ConciseMagicFile"), + .enableUpcomingFeature("DisableOutwardActorInference"), + .enableUpcomingFeature("StrictConcurrency"), + .enableExperimentalFeature("StrictConcurrency=complete"), +] } diff --git a/Sources/QueuesFluentDriver/FluentQueue.swift b/Sources/QueuesFluentDriver/FluentQueue.swift index 16cb6d2..ce0d7f8 100644 --- a/Sources/QueuesFluentDriver/FluentQueue.swift +++ b/Sources/QueuesFluentDriver/FluentQueue.swift @@ -79,7 +79,7 @@ public struct FluentQueue: Queue, Sendable { .where(SQLFunction("coalesce", args: JobModel.sqlColumn(\.$data.$delayUntil), SQLFunction("now")), .lessThanOrEqual, SQLFunction("now")) .orderBy(JobModel.sqlColumn(\.$data.$delayUntil)) .limit(1) - .lockingClause(SQLSkipLocked.forUpdateSkipLocked) + .lockingClause(SQLLockingClauseWithSkipLocked.updateSkippingLocked) if self.sqlDb.dialect.supportsReturning { return try await self.sqlDb.update(JobModel.sqlTable) diff --git a/Sources/QueuesFluentDriver/SQLSkipLocked.swift b/Sources/QueuesFluentDriver/SQLSkipLocked.swift index 9f2aa78..0b44299 100644 --- a/Sources/QueuesFluentDriver/SQLSkipLocked.swift +++ b/Sources/QueuesFluentDriver/SQLSkipLocked.swift @@ -1,20 +1,26 @@ import SQLKit -enum SQLSkipLocked: SQLExpression { - case forUpdateSkipLocked - case forShareSkipLocked +enum SQLLockingClauseWithSkipLocked: SQLExpression { + /// Request an exclusive "writer" lock, skipping rows that are already locked. + case updateSkippingLocked + + /// Request a shared "reader" lock, skipping rows that are already locked. + /// + /// > Note: This is the "lightest" locking that is supported by both Postgres and MySQL. + case shareSkippingLocked + // See `SQLExpression.serialize(to:)`. func serialize(to serializer: inout SQLSerializer) { - guard serializer.dialect.name != "sqlite" else { - return - } - - switch self { - case .forUpdateSkipLocked: - serializer.write("FOR UPDATE SKIP LOCKED") - case .forShareSkipLocked: - // This is the "lightest" locking that is supported by both Postgres and Mysql - serializer.write("FOR SHARE SKIP LOCKED") + serializer.statement { + switch self { + case .updateSkippingLocked: + guard $0.dialect.exclusiveSelectLockExpression != nil else { return } + $0.append(SQLLockingClause.update) + case .shareSkippingLocked: + guard $0.dialect.sharedSelectLockExpression != nil else { return } + $0.append(SQLLockingClause.share) + } + $0.append("SKIP LOCKED") } } }