Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let package = Package(
targets: ["Lockman"])
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", exact: "1.22.3"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", exact: "1.23.0"),
.package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"603.0.0"),
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.3"),
.package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"),
Expand Down
2 changes: 1 addition & 1 deletion Package@swift-6.0.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let package = Package(
targets: ["Lockman"])
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", exact: "1.22.3"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", exact: "1.23.0"),
.package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"603.0.0"),
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.3"),
.package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"),
Expand Down
28 changes: 18 additions & 10 deletions Sources/Lockman/Composable/Effect+Lockman.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,18 @@ extension Effect {
unlockOption: unlockOption,
onSuccess: { action, unlock in
let shouldBeCancellable = action.createLockmanInfo().isCancellationTarget
let cancellableEffect = shouldBeCancellable ? concatenatedEffect.cancellable(id: boundaryId) : concatenatedEffect
let cancellableEffect =
shouldBeCancellable ? concatenatedEffect.cancellable(id: boundaryId) : concatenatedEffect
return Effect<Action>.concatenate([cancellableEffect, .run { _ in unlock() }])
},
onSuccessWithPrecedingCancellation: { action, error, unlock in
let shouldBeCancellable = action.createLockmanInfo().isCancellationTarget
let cancellableEffect = shouldBeCancellable ? concatenatedEffect.cancellable(id: boundaryId) : concatenatedEffect
let cancellableEffect =
shouldBeCancellable ? concatenatedEffect.cancellable(id: boundaryId) : concatenatedEffect
let completeEffect = Effect<Action>.concatenate([cancellableEffect, .run { _ in unlock() }])

let cancellationError = LockmanCancellationError(action: action, boundaryId: boundaryId, reason: error)

let cancellationError = LockmanCancellationError(
action: action, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .concatenate([
.run { send in await lockFailure(cancellationError, send) },
Expand All @@ -101,7 +104,8 @@ extension Effect {
return .concatenate([.cancel(id: boundaryId), completeEffect])
},
onCancel: { action, error in
let cancellationError = LockmanCancellationError(action: action, boundaryId: boundaryId, reason: error)
let cancellationError = LockmanCancellationError(
action: action, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .run { send in await lockFailure(cancellationError, send) }
}
Expand Down Expand Up @@ -200,15 +204,18 @@ extension Effect {
unlockOption: unlockOption,
onSuccess: { action, unlock in
let shouldBeCancellable = action.createLockmanInfo().isCancellationTarget
let cancellableEffect = shouldBeCancellable ? operation.cancellable(id: boundaryId) : operation
let cancellableEffect =
shouldBeCancellable ? operation.cancellable(id: boundaryId) : operation
return Effect<Action>.concatenate([cancellableEffect, .run { _ in unlock() }])
},
onSuccessWithPrecedingCancellation: { action, error, unlock in
let shouldBeCancellable = action.createLockmanInfo().isCancellationTarget
let cancellableEffect = shouldBeCancellable ? operation.cancellable(id: boundaryId) : operation
let cancellableEffect =
shouldBeCancellable ? operation.cancellable(id: boundaryId) : operation
let completeEffect = Effect<Action>.concatenate([cancellableEffect, .run { _ in unlock() }])

let cancellationError = LockmanCancellationError(action: action, boundaryId: boundaryId, reason: error)

let cancellationError = LockmanCancellationError(
action: action, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .concatenate([
.run { send in await lockFailure(cancellationError, send) },
Expand All @@ -219,7 +226,8 @@ extension Effect {
return .concatenate([.cancel(id: boundaryId), completeEffect])
},
onCancel: { action, error in
let cancellationError = LockmanCancellationError(action: action, boundaryId: boundaryId, reason: error)
let cancellationError = LockmanCancellationError(
action: action, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .run { send in await lockFailure(cancellationError, send) }
}
Expand Down
12 changes: 8 additions & 4 deletions Sources/Lockman/Composable/LockmanReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,12 @@ public struct LockmanReducer<Base: Reducer>: Reducer {
let effect = self.base.reduce(into: &state, action: action)
let shouldBeCancellable = lockmanAction.createLockmanInfo().isCancellationTarget
let cancellableEffect = shouldBeCancellable ? effect.cancellable(id: boundaryId) : effect
let completeEffect = Effect<Action>.concatenate([cancellableEffect, .run { _ in unlock() }])

let cancellationError = LockmanCancellationError(action: lockmanAction, boundaryId: boundaryId, reason: error)
let completeEffect = Effect<Action>.concatenate([
cancellableEffect, .run { _ in unlock() },
])

let cancellationError = LockmanCancellationError(
action: lockmanAction, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .concatenate([
.run { send in await lockFailure(cancellationError, send) },
Expand All @@ -112,7 +115,8 @@ public struct LockmanReducer<Base: Reducer>: Reducer {
return .concatenate([.cancel(id: boundaryId), completeEffect])
},
onCancel: { _, error in
let cancellationError = LockmanCancellationError(action: lockmanAction, boundaryId: boundaryId, reason: error)
let cancellationError = LockmanCancellationError(
action: lockmanAction, boundaryId: boundaryId, reason: error)
if let lockFailure = lockFailure {
return .run { send in await lockFailure(cancellationError, send) }
}
Expand Down
14 changes: 8 additions & 6 deletions Sources/Lockman/Core/LockmanManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ extension LockmanManager {
/// action: action,
/// boundaryId: boundaryId,
/// unlockOption: nil,
/// onSuccess: { _, unlock in
/// onSuccess: { _, unlock in
/// defer { unlock() }
/// performWork()
/// return true
Expand All @@ -346,29 +346,31 @@ extension LockmanManager {
boundaryId: B,
unlockOption: LockmanUnlockOption?,
onSuccess: (A, @escaping @Sendable () -> Void) -> T,
onSuccessWithPrecedingCancellation: (A, any LockmanPrecedingCancellationError, @escaping @Sendable () -> Void) -> T,
onSuccessWithPrecedingCancellation: (
A, any LockmanPrecedingCancellationError, @escaping @Sendable () -> Void
) -> T,
onCancel: (A, any LockmanError) -> T,
onError: (A, any Error) -> T
) -> T {
do {
// Capture lockmanInfo once to ensure consistent uniqueId throughout lock lifecycle
let lockmanInfo = action.createLockmanInfo()

// Acquire lock with integrated unlock token
let result = try acquireLock(
lockmanInfo: lockmanInfo,
boundaryId: boundaryId,
unlockOption: unlockOption ?? action.unlockOption
)

// Handle lock result with callback execution
switch result {
case .success(let unlockToken):
return onSuccess(action, unlockToken.callAsFunction)

case .successWithPrecedingCancellation(let unlockToken, let error):
return onSuccessWithPrecedingCancellation(action, error, unlockToken.callAsFunction)

case .cancel(let error):
return onCancel(action, error)
}
Expand Down
1 change: 0 additions & 1 deletion Sources/Lockman/Core/LockmanResult.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/// The result of attempting to acquire a lock with integrated unlock capability.
///
/// This enum represents the possible outcomes when a strategy attempts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,13 @@ extension LockmanStrategyResult {
return true
case (.cancel(let lhsError), .cancel(let rhsError)):
return String(describing: lhsError) == String(describing: rhsError)
case (.successWithPrecedingCancellation(let lhsError), .successWithPrecedingCancellation(let rhsError)):
case (
.successWithPrecedingCancellation(let lhsError),
.successWithPrecedingCancellation(let rhsError)
):
return String(describing: lhsError) == String(describing: rhsError)
default:
return false
}
}
}
}
4 changes: 3 additions & 1 deletion Tests/LockmanTests/Supports/TestSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ public final class TestSingleExecutionStrategy: LockmanStrategy, @unchecked Send
LockmanStrategyId(name: "TestSingleExecutionStrategy")
}

public func canLock<B: LockmanBoundaryId>(boundaryId: B, info: TestLockmanInfo) -> LockmanStrategyResult {
public func canLock<B: LockmanBoundaryId>(boundaryId: B, info: TestLockmanInfo)
-> LockmanStrategyResult
{
lock.withLock {
if lockedActions.contains(info.actionId) {
let error = LockmanCancellationError(
Expand Down
Loading
Loading