-
Notifications
You must be signed in to change notification settings - Fork 6
Implement an Arithmetic Request supporting increment and decrement operations #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
764e3f7
882b5a0
f504be3
b124153
0bb4f8b
eac8f0a
1e79a89
c486acc
f863db2
153b018
3ab280f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -424,4 +424,58 @@ public actor MemcachedConnection { | |
throw MemcachedConnectionError.connectionShutdown | ||
} | ||
} | ||
|
||
// MARK: - Increment a Value | ||
|
||
/// Increment the value for an existing key in the Memcache server by a specified amount. | ||
/// | ||
/// - Parameters: | ||
/// - key: The key for the value to increment. | ||
/// - amount: The `UInt64` amount to increment the value by. | ||
/// - Throws: A `MemcachedConnectionError` if the connection to the Memcached server is shut down. | ||
public func increment(_ key: String, amount: UInt64) async throws { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use Int here and precondition that it is larger than 0 |
||
switch self.state { | ||
case .initial(_, _, _, _), | ||
.running: | ||
|
||
var flags = MemcachedFlags() | ||
flags.arithmeticMode = .increment | ||
flags.arithmeticDelta = amount | ||
|
||
let command = MemcachedRequest.ArithmeticCommand(key: key, flags: flags) | ||
let request = MemcachedRequest.arithmetic(command) | ||
|
||
_ = try await self.sendRequest(request) | ||
|
||
case .finished: | ||
throw MemcachedConnectionError.connectionShutdown | ||
} | ||
} | ||
|
||
// MARK: - Decrement a Value | ||
|
||
/// Decrement the value for an existing key in the Memcache server by a specified amount. | ||
/// | ||
/// - Parameters: | ||
/// - key: The key for the value to decrement. | ||
/// - amount: The `UInt64` amount to decrement the value by. | ||
/// - Throws: A `MemcachedConnectionError` if the connection to the Memcached server is shut down. | ||
public func decrement(_ key: String, amount: UInt64) async throws { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here and adjust the doc comment as well please |
||
switch self.state { | ||
case .initial(_, _, _, _), | ||
.running: | ||
|
||
var flags = MemcachedFlags() | ||
flags.arithmeticMode = .decrement | ||
flags.arithmeticDelta = amount | ||
|
||
let command = MemcachedRequest.ArithmeticCommand(key: key, flags: flags) | ||
let request = MemcachedRequest.arithmetic(command) | ||
|
||
_ = try await self.sendRequest(request) | ||
|
||
case .finished: | ||
throw MemcachedConnectionError.connectionShutdown | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,16 @@ struct MemcachedFlags { | |
/// The default mode is 'set'. | ||
var storageMode: StorageMode? | ||
|
||
/// Flag 'M' for the 'ma' (meta arithmetic) command. | ||
/// | ||
/// Represents the mode of the 'ma' command, which determines the behavior of the arithmetic operation. | ||
var arithmeticMode: ArithmeticMode? | ||
|
||
/// Flag 'D' for the 'ma' (meta arithmetic) command. | ||
/// | ||
/// Represents the delta to apply to the 'ma' command. The default value is 1. | ||
var arithmeticDelta: UInt64? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this an associated value of the arithmetic mode enum please |
||
|
||
init() {} | ||
} | ||
|
||
|
@@ -60,4 +70,12 @@ enum StorageMode: Equatable, Hashable { | |
case replace | ||
} | ||
|
||
/// Enum representing the mode for the 'ma' (meta arithmetic) command in Memcached (corresponding to the 'M' flag). | ||
enum ArithmeticMode: Equatable, Hashable { | ||
/// 'increment' command. If applied, it increases the numerical value of the item. | ||
case increment | ||
/// 'decrement' command. If applied, it decreases the numerical value of the item. | ||
case decrement | ||
} | ||
|
||
extension MemcachedFlags: Hashable {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,14 +33,15 @@ extension MemcachedValue where Self: FixedWidthInteger { | |
/// | ||
/// - Parameter buffer: The ByteBuffer to which the integer should be written. | ||
public func writeToBuffer(_ buffer: inout ByteBuffer) { | ||
buffer.writeInteger(self) | ||
buffer.writeString(String(self)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems wrong. If you want to store an integer we shouldn't convert it to a string. Is this the problem you encountered where you set a key and then want to increment it but the type in memcache was wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, for example when I called set with a value of say 100 the request that was being written looked like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could also make use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the root problem here is that memcache is operating on the values interpreted as ASCII and not the raw byte values right? So decrement expects that the value for a key is an ASCII string representing an integer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that is correct, since the protocol is text based its wanting to receive the values as ASCII strings. we can fall back on making use of |
||
} | ||
|
||
/// Reads a FixedWidthInteger from a ByteBuffer. | ||
/// | ||
/// - Parameter buffer: The ByteBuffer from which the value should be read. | ||
public static func readFromBuffer(_ buffer: inout ByteBuffer) -> Self? { | ||
return buffer.readInteger() | ||
guard let string = buffer.readString(length: buffer.readableBytes)?.trimmingCharacters(in: .whitespacesAndNewlines) else { return nil } | ||
return Self(string) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can't specify a storage mode and arithmetic mode. Can we add a precondition somewhere to check for this