@@ -17,6 +17,10 @@ import NIOCore
17
17
import Dependencies
18
18
import DependenciesMacros
19
19
20
+ @globalActor
21
+ actor RedisSingletonActor {
22
+ static let shared = RedisSingletonActor ( )
23
+ }
20
24
21
25
@DependencyClient
22
26
struct RedisClient {
@@ -42,11 +46,11 @@ extension RedisClient: DependencyKey {
42
46
static var liveValue : RedisClient {
43
47
. init(
44
48
set: { key, value, expiresIn in
45
- try await Redis . shared. set ( key: key, value: value, expiresIn: expiresIn)
49
+ try await Redis . shared ( ) . set ( key: key, value: value, expiresIn: expiresIn)
46
50
} ,
47
- get: { key in try await Redis . shared. get ( key: key) } ,
48
- expire: { key, ttl in try await Redis . shared. expire ( key: key, after: ttl) } ,
49
- increment: { key, value in try await Redis . shared. increment ( key: key, by: value) }
51
+ get: { key in try await Redis . shared ( ) . get ( key: key) } ,
52
+ expire: { key, ttl in try await Redis . shared ( ) . expire ( key: key, after: ttl) } ,
53
+ increment: { key, value in try await Redis . shared ( ) . increment ( key: key, by: value) }
50
54
)
51
55
}
52
56
}
@@ -79,30 +83,27 @@ extension RedisClient {
79
83
80
84
private actor Redis {
81
85
var client : RediStack . RedisClient
82
- static private var task : Task < Redis , Swift . Error > ?
86
+ @ RedisSingletonActor private static var _shared : Redis ?
83
87
84
- static var shared : Redis {
85
- get async throws {
86
- if let task {
87
- return try await task. value
88
- }
89
- let task = Task < Redis , Swift . Error > {
90
- var attemptsLeft = maxConnectionAttempts
91
- while attemptsLeft > 0 {
92
- do {
93
- return try await Redis ( )
94
- } catch {
95
- attemptsLeft -= 1
96
- @Dependency ( \. logger) var logger
97
- logger. warning ( " Redis connection failed, \( attemptsLeft) attempts left. Error: \( error) " )
98
- try ? await Task . sleep ( for: . milliseconds( 500 ) )
99
- }
100
- }
101
- throw Error . unavailable
88
+ @RedisSingletonActor
89
+ static func shared( ) async throws -> Redis {
90
+ if let existing = _shared {
91
+ return existing
92
+ }
93
+ var attemptsLeft = maxConnectionAttempts
94
+ while attemptsLeft > 0 {
95
+ do {
96
+ let instance = try await Redis ( )
97
+ _shared = instance
98
+ return instance
99
+ } catch {
100
+ attemptsLeft -= 1
101
+ @Dependency ( \. logger) var logger
102
+ logger. warning ( " Redis connection failed, \( attemptsLeft) attempts left. Error: \( error) " )
103
+ try ? await Task . sleep ( for: . milliseconds( 500 ) )
102
104
}
103
- self . task = task
104
- return try await task. value
105
105
}
106
+ throw Error . unavailable
106
107
}
107
108
108
109
enum Error : Swift . Error {
0 commit comments