14
14
import Foundation
15
15
16
16
// TODO(pp): Implement slow consumer
17
- // TODO(pp): Add queue subscribe
18
17
public class NatsSubscription : AsyncSequence {
19
18
public typealias Element = NatsMessage
20
19
public typealias AsyncIterator = SubscriptionIterator
21
20
22
21
public let subject : String
22
+ public let queue : String ?
23
23
internal var max : UInt64 ?
24
24
internal var delivered : UInt64 = 0
25
25
internal let sid : UInt64
@@ -34,14 +34,21 @@ public class NatsSubscription: AsyncSequence {
34
34
35
35
private static let defaultSubCapacity : UInt64 = 512 * 1024
36
36
37
- convenience init ( sid: UInt64 , subject: String , conn: ConnectionHandler ) {
38
- self . init (
39
- sid: sid, subject: subject, capacity: NatsSubscription . defaultSubCapacity, conn: conn)
37
+ convenience init ( sid: UInt64 , subject: String , queue : String ? , conn: ConnectionHandler ) throws {
38
+ try self . init (
39
+ sid: sid, subject: subject, queue : queue , capacity: NatsSubscription . defaultSubCapacity, conn: conn)
40
40
}
41
41
42
- init ( sid: UInt64 , subject: String , capacity: UInt64 , conn: ConnectionHandler ) {
42
+ init ( sid: UInt64 , subject: String , queue: String ? , capacity: UInt64 , conn: ConnectionHandler ) throws {
43
+ if !NatsSubscription. validSubject ( subject) {
44
+ throw NatsError . SubscriptionError. invalidSubject
45
+ }
46
+ if let queue, !NatsSubscription. validQueue ( queue) {
47
+ throw NatsError . SubscriptionError. invalidQueue
48
+ }
43
49
self . sid = sid
44
50
self . subject = subject
51
+ self . queue = queue
45
52
self . capacity = capacity
46
53
self . buffer = [ ]
47
54
self . conn = conn
@@ -150,4 +157,26 @@ public class NatsSubscription: AsyncSequence {
150
157
}
151
158
return try await self . conn. unsubscribe ( sub: self , max: after)
152
159
}
160
+
161
+ // validateSubject will do a basic subject validation.
162
+ // Spaces are not allowed and all tokens should be > 0 in length.
163
+ private static func validSubject( _ subj: String ) -> Bool {
164
+ let whitespaceCharacterSet = CharacterSet . whitespacesAndNewlines
165
+ if subj. rangeOfCharacter ( from: whitespaceCharacterSet) != nil {
166
+ return false
167
+ }
168
+ let tokens = subj. split ( separator: " . " )
169
+ for token in tokens {
170
+ if token. isEmpty {
171
+ return false
172
+ }
173
+ }
174
+ return true
175
+ }
176
+
177
+ // validQueue will check a queue name for whitespaces.
178
+ private static func validQueue( _ queue: String ) -> Bool {
179
+ let whitespaceCharacterSet = CharacterSet . whitespacesAndNewlines
180
+ return queue. rangeOfCharacter ( from: whitespaceCharacterSet) == nil
181
+ }
153
182
}
0 commit comments