mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-08 00:43:06 +00:00
* queue driver refactor (#2753) * chore(archive): archive refactor (#2752) * chore(archive): sqlite driver refactor (#2754) * chore(archive): postgres driver refactor (#2755) * chore(archive): renaming & copies (#2751) * posgres legacy: stop using the storedAt field * migration script 6: we still need the id column The id column is needed because it contains the message digest which is used in store v2, and we need to keep support to store v2 for a while * legacy archive: set target migration version to 6 * waku_node: try to use wakuLegacyArchive if wakuArchive is nil * node_factory, waku_node: mount legacy and future store simultaneously We want the nwaku node to simultaneously support store-v2 requests and store-v3 requests. Only the legacy archive is in charge of archiving messages, and the archived information is suitable to fulfill both store-v2 and store-v3 needs. * postgres_driver: adding temporary code until store-v2 is removed --------- Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com> Co-authored-by: gabrielmer <101006718+gabrielmer@users.noreply.github.com> Co-authored-by: Ivan Folgueira Bande <ivansete@status.im>
69 lines
2.9 KiB
Nim
69 lines
2.9 KiB
Nim
when (NimMajor, NimMinor) < (1, 4):
|
|
{.push raises: [Defect].}
|
|
else:
|
|
{.push raises: [].}
|
|
|
|
import results, chronicles, chronos
|
|
import ../driver, ../retention_policy
|
|
|
|
logScope:
|
|
topics = "waku archive retention_policy"
|
|
|
|
const DefaultCapacity*: int = 25_000
|
|
|
|
const MaxOverflow = 1.3
|
|
|
|
type
|
|
# CapacityRetentionPolicy implements auto deletion as follows:
|
|
# - The sqlite DB will driver up to `totalCapacity = capacity` * `MaxOverflow` messages,
|
|
# giving an overflowWindow of `capacity * (MaxOverflow - 1) = overflowWindow`.
|
|
#
|
|
# - In case of an overflow, messages are sorted by `receiverTimestamp` and the oldest ones are
|
|
# deleted. The number of messages that get deleted is `(overflowWindow / 2) = deleteWindow`,
|
|
# bringing the total number of driverd messages back to `capacity + (overflowWindow / 2)`.
|
|
#
|
|
# The rationale for batch deleting is efficiency. We keep half of the overflow window in addition
|
|
# to `capacity` because we delete the oldest messages with respect to `receiverTimestamp` instead of
|
|
# `senderTimestamp`. `ReceiverTimestamp` is guaranteed to be set, while senders could omit setting
|
|
# `senderTimestamp`. However, `receiverTimestamp` can differ from node to node for the same message.
|
|
# So sorting by `receiverTimestamp` might (slightly) prioritize some actually older messages and we
|
|
# compensate that by keeping half of the overflow window.
|
|
CapacityRetentionPolicy* = ref object of RetentionPolicy
|
|
capacity: int
|
|
# represents both the number of messages that are persisted in the sqlite DB (excl. the overflow window explained above), and the number of messages that get loaded via `getAll`.
|
|
totalCapacity: int # = capacity * MaxOverflow
|
|
deleteWindow: int
|
|
# = capacity * (MaxOverflow - 1) / 2; half of the overflow window, the amount of messages deleted when overflow occurs
|
|
|
|
proc calculateTotalCapacity(capacity: int, overflow: float): int =
|
|
int(float(capacity) * overflow)
|
|
|
|
proc calculateOverflowWindow(capacity: int, overflow: float): int =
|
|
int(float(capacity) * (overflow - 1))
|
|
|
|
proc calculateDeleteWindow(capacity: int, overflow: float): int =
|
|
calculateOverflowWindow(capacity, overflow) div 2
|
|
|
|
proc new*(T: type CapacityRetentionPolicy, capacity = DefaultCapacity): T =
|
|
let
|
|
totalCapacity = calculateTotalCapacity(capacity, MaxOverflow)
|
|
deleteWindow = calculateDeleteWindow(capacity, MaxOverflow)
|
|
|
|
CapacityRetentionPolicy(
|
|
capacity: capacity, totalCapacity: totalCapacity, deleteWindow: deleteWindow
|
|
)
|
|
|
|
method execute*(
|
|
p: CapacityRetentionPolicy, driver: ArchiveDriver
|
|
): Future[RetentionPolicyResult[void]] {.async.} =
|
|
let numMessages = (await driver.getMessagesCount()).valueOr:
|
|
return err("failed to get messages count: " & error)
|
|
|
|
if numMessages < p.totalCapacity:
|
|
return ok()
|
|
|
|
(await driver.deleteOldestMessagesNotWithinLimit(limit = p.capacity + p.deleteWindow)).isOkOr:
|
|
return err("deleting oldest messages failed: " & error)
|
|
|
|
return ok()
|