mirror of
https://github.com/logos-messaging/nim-chat-sdk.git
synced 2026-01-07 16:43:11 +00:00
fix: add ref object and serializable
This commit is contained in:
parent
836a04e6ba
commit
f04e6ae7aa
@ -2,24 +2,27 @@ import std/[times, deques]
|
|||||||
import chronos
|
import chronos
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Serializable* = concept x
|
||||||
|
x.toBytes() is seq[byte]
|
||||||
|
|
||||||
MessagePriority* = enum
|
MessagePriority* = enum
|
||||||
Critical = 0
|
Critical = 0
|
||||||
Normal = 1
|
Normal = 1
|
||||||
Optional = 2
|
Optional = 2
|
||||||
|
|
||||||
QueuedMessage*[T] = object
|
QueuedMessage*[T: Serializable] = ref object of RootObj
|
||||||
messageId*: string
|
messageId*: string
|
||||||
msg*: T
|
msg*: T
|
||||||
priority*: MessagePriority
|
priority*: MessagePriority
|
||||||
queuedAt*: float
|
queuedAt*: float
|
||||||
|
|
||||||
MessageSender*[T] = proc(messageId: string, msg: T): Future[bool] {.async.}
|
MessageSender*[T: Serializable] = proc(messageId: string, msg: T): Future[bool] {.async.}
|
||||||
|
|
||||||
RateLimitManager*[T] = ref object
|
RateLimitManager*[T: Serializable] = ref object
|
||||||
messageCount*: int = 100 # Default to 100 messages
|
messageCount*: int = 100 # Default to 100 messages
|
||||||
epochDurationSec*: int = 600 # Default to 10 minutes
|
epochDurationSec*: int = 600 # Default to 10 minutes
|
||||||
currentCount*: int
|
currentCount*: int
|
||||||
currentEpoch*: int64
|
lastResetTime*: float
|
||||||
criticalQueue*: Deque[QueuedMessage[T]]
|
criticalQueue*: Deque[QueuedMessage[T]]
|
||||||
normalQueue*: Deque[QueuedMessage[T]]
|
normalQueue*: Deque[QueuedMessage[T]]
|
||||||
optionalQueue*: Deque[QueuedMessage[T]]
|
optionalQueue*: Deque[QueuedMessage[T]]
|
||||||
@ -27,15 +30,12 @@ type
|
|||||||
isRunning*: bool
|
isRunning*: bool
|
||||||
sendTask*: Future[void]
|
sendTask*: Future[void]
|
||||||
|
|
||||||
proc getCurrentEpoch(epochDurationSec: int): int64 =
|
proc newRateLimitManager*[T: Serializable](messageCount: int, epochDurationSec: int, sender: MessageSender[T]): RateLimitManager[T] =
|
||||||
int64(epochTime() / float(epochDurationSec))
|
|
||||||
|
|
||||||
proc newRateLimitManager*[T](messageCount: int, epochDurationSec: int, sender: MessageSender[T]): RateLimitManager[T] =
|
|
||||||
RateLimitManager[T](
|
RateLimitManager[T](
|
||||||
messageCount: messageCount,
|
messageCount: messageCount,
|
||||||
epochDurationSec: epochDurationSec,
|
epochDurationSec: epochDurationSec,
|
||||||
currentCount: 0,
|
currentCount: 0,
|
||||||
currentEpoch: getCurrentEpoch(epochDurationSec),
|
lastResetTime: epochTime(),
|
||||||
criticalQueue: initDeque[QueuedMessage[T]](),
|
criticalQueue: initDeque[QueuedMessage[T]](),
|
||||||
normalQueue: initDeque[QueuedMessage[T]](),
|
normalQueue: initDeque[QueuedMessage[T]](),
|
||||||
optionalQueue: initDeque[QueuedMessage[T]](),
|
optionalQueue: initDeque[QueuedMessage[T]](),
|
||||||
@ -43,18 +43,18 @@ proc newRateLimitManager*[T](messageCount: int, epochDurationSec: int, sender: M
|
|||||||
isRunning: false
|
isRunning: false
|
||||||
)
|
)
|
||||||
|
|
||||||
proc updateEpochIfNeeded[T](manager: RateLimitManager[T]) =
|
proc updateEpochIfNeeded[T: Serializable](manager: RateLimitManager[T]) =
|
||||||
let newEpoch = getCurrentEpoch(manager.epochDurationSec)
|
let now = epochTime()
|
||||||
if newEpoch > manager.currentEpoch:
|
if now - manager.lastResetTime >= float(manager.epochDurationSec):
|
||||||
manager.currentEpoch = newEpoch
|
manager.lastResetTime = now
|
||||||
manager.currentCount = 0
|
manager.currentCount = 0
|
||||||
|
|
||||||
proc getUsagePercent[T](manager: RateLimitManager[T]): float =
|
proc getUsagePercent[T: Serializable](manager: RateLimitManager[T]): float =
|
||||||
if manager.messageCount == 0:
|
if manager.messageCount == 0:
|
||||||
return 1.0
|
return 1.0
|
||||||
float(manager.currentCount) / float(manager.messageCount)
|
float(manager.currentCount) / float(manager.messageCount)
|
||||||
|
|
||||||
proc queueForSend*[T](manager: RateLimitManager[T], messageId: string, msg: T, priority: MessagePriority) =
|
proc queueForSend*[T: Serializable](manager: RateLimitManager[T], messageId: string, msg: T, priority: MessagePriority) =
|
||||||
manager.updateEpochIfNeeded()
|
manager.updateEpochIfNeeded()
|
||||||
|
|
||||||
let queuedMsg = QueuedMessage[T](
|
let queuedMsg = QueuedMessage[T](
|
||||||
@ -94,7 +94,7 @@ proc queueForSend*[T](manager: RateLimitManager[T], messageId: string, msg: T, p
|
|||||||
of Optional:
|
of Optional:
|
||||||
manager.optionalQueue.addLast(queuedMsg)
|
manager.optionalQueue.addLast(queuedMsg)
|
||||||
|
|
||||||
proc getNextMessage[T](manager: RateLimitManager[T]): QueuedMessage[T] =
|
proc getNextMessage[T: Serializable](manager: RateLimitManager[T]): QueuedMessage[T] =
|
||||||
# Priority order: Critical -> Normal -> Optional
|
# Priority order: Critical -> Normal -> Optional
|
||||||
if manager.criticalQueue.len > 0:
|
if manager.criticalQueue.len > 0:
|
||||||
return manager.criticalQueue.popFirst()
|
return manager.criticalQueue.popFirst()
|
||||||
@ -105,10 +105,10 @@ proc getNextMessage[T](manager: RateLimitManager[T]): QueuedMessage[T] =
|
|||||||
else:
|
else:
|
||||||
raise newException(ValueError, "No messages in queue")
|
raise newException(ValueError, "No messages in queue")
|
||||||
|
|
||||||
proc hasMessages[T](manager: RateLimitManager[T]): bool =
|
proc hasMessages[T: Serializable](manager: RateLimitManager[T]): bool =
|
||||||
manager.criticalQueue.len > 0 or manager.normalQueue.len > 0 or manager.optionalQueue.len > 0
|
manager.criticalQueue.len > 0 or manager.normalQueue.len > 0 or manager.optionalQueue.len > 0
|
||||||
|
|
||||||
proc sendLoop*[T](manager: RateLimitManager[T]): Future[void] {.async.} =
|
proc sendLoop*[T: Serializable](manager: RateLimitManager[T]): Future[void] {.async.} =
|
||||||
manager.isRunning = true
|
manager.isRunning = true
|
||||||
|
|
||||||
while manager.isRunning:
|
while manager.isRunning:
|
||||||
@ -153,11 +153,11 @@ proc sendLoop*[T](manager: RateLimitManager[T]): Future[void] {.async.} =
|
|||||||
except:
|
except:
|
||||||
await sleepAsync(chronos.seconds(1)) # Wait longer on error
|
await sleepAsync(chronos.seconds(1)) # Wait longer on error
|
||||||
|
|
||||||
proc start*[T](manager: RateLimitManager[T]): Future[void] {.async.} =
|
proc start*[T: Serializable](manager: RateLimitManager[T]): Future[void] {.async.} =
|
||||||
if not manager.isRunning:
|
if not manager.isRunning:
|
||||||
manager.sendTask = manager.sendLoop()
|
manager.sendTask = manager.sendLoop()
|
||||||
|
|
||||||
proc stop*[T](manager: RateLimitManager[T]): Future[void] {.async.} =
|
proc stop*[T: Serializable](manager: RateLimitManager[T]): Future[void] {.async.} =
|
||||||
if manager.isRunning:
|
if manager.isRunning:
|
||||||
manager.isRunning = false
|
manager.isRunning = false
|
||||||
if not manager.sendTask.isNil:
|
if not manager.sendTask.isNil:
|
||||||
@ -167,7 +167,7 @@ proc stop*[T](manager: RateLimitManager[T]): Future[void] {.async.} =
|
|||||||
except CancelledError:
|
except CancelledError:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc getQueueStatus*[T](manager: RateLimitManager[T]): tuple[critical: int, normal: int, optional: int, total: int] =
|
proc getQueueStatus*[T: Serializable](manager: RateLimitManager[T]): tuple[critical: int, normal: int, optional: int, total: int] =
|
||||||
(
|
(
|
||||||
critical: manager.criticalQueue.len,
|
critical: manager.criticalQueue.len,
|
||||||
normal: manager.normalQueue.len,
|
normal: manager.normalQueue.len,
|
||||||
@ -175,7 +175,7 @@ proc getQueueStatus*[T](manager: RateLimitManager[T]): tuple[critical: int, norm
|
|||||||
total: manager.criticalQueue.len + manager.normalQueue.len + manager.optionalQueue.len
|
total: manager.criticalQueue.len + manager.normalQueue.len + manager.optionalQueue.len
|
||||||
)
|
)
|
||||||
|
|
||||||
proc getCurrentQuota*[T](manager: RateLimitManager[T]): tuple[total: int, used: int, remaining: int] =
|
proc getCurrentQuota*[T: Serializable](manager: RateLimitManager[T]): tuple[total: int, used: int, remaining: int] =
|
||||||
(
|
(
|
||||||
total: manager.messageCount,
|
total: manager.messageCount,
|
||||||
used: manager.currentCount,
|
used: manager.currentCount,
|
||||||
|
|||||||
@ -12,6 +12,17 @@ type
|
|||||||
content: string
|
content: string
|
||||||
id: int
|
id: int
|
||||||
|
|
||||||
|
# Implement Serializable for test types
|
||||||
|
proc toBytes*(s: string): seq[byte] =
|
||||||
|
cast[seq[byte]](s)
|
||||||
|
|
||||||
|
proc toBytes*(msg: TestMessage): seq[byte] =
|
||||||
|
result = toBytes(msg.content)
|
||||||
|
result.add(cast[seq[byte]](@[byte(msg.id)]))
|
||||||
|
|
||||||
|
proc toBytes*(i: int): seq[byte] =
|
||||||
|
cast[seq[byte]](@[byte(i)])
|
||||||
|
|
||||||
suite "Rate Limit Manager":
|
suite "Rate Limit Manager":
|
||||||
setup:
|
setup:
|
||||||
## Given
|
## Given
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user