-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Postgres partition implementation (#2506)
* postgres: first step to implement partition management * postgres_driver: use of times.now().toTime().toUnix() instead of Moment.now() * postgres migrations: set new version to 2 * test_driver_postgres: use of assert instead of require and avoid using times.now() * postgres_driver: better implementation of the reset method with partitions * Remove createMessageTable, init, and deleteMessageTable procs * postgres: ensure we use the version 15.4 in tests * postgres_driver.nim: enhance debug logs partition addition * ci.yml: ensure logs are printed without colors * postgres_driver: starting the loop factory in an asynchronous task * postgres_driver: log partition name and size when removing a partition
- Loading branch information
1 parent
beba14d
commit 161a10e
Showing
11 changed files
with
445 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
waku/waku_archive/driver/postgres_driver/partitions_manager.nim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
|
||
## This module is aimed to handle the creation and truncation of partition tables | ||
## in order to limit the space occupied in disk by the database. | ||
## | ||
## The created partitions are referenced by the 'storedAt' field. | ||
## | ||
|
||
import | ||
std/deques | ||
import | ||
chronos, | ||
chronicles | ||
|
||
logScope: | ||
topics = "waku archive partitions_manager" | ||
|
||
## The time range has seconds resolution | ||
type TimeRange* = tuple[beginning: int64, `end`: int64] | ||
|
||
type | ||
Partition = object | ||
name: string | ||
timeRange: TimeRange | ||
|
||
PartitionManager* = ref object | ||
partitions: Deque[Partition] # FIFO of partition table names. The first is the oldest partition | ||
|
||
proc new*(T: type PartitionManager): T = | ||
return PartitionManager() | ||
|
||
proc getPartitionFromDateTime*(self: PartitionManager, | ||
targetMoment: int64): | ||
Result[Partition, string] = | ||
## Returns the partition name that might store a message containing the passed timestamp. | ||
## In order words, it simply returns the partition name which contains the given timestamp. | ||
## targetMoment - represents the time of interest, measured in seconds since epoch. | ||
|
||
if self.partitions.len == 0: | ||
return err("There are no partitions") | ||
|
||
for partition in self.partitions: | ||
let timeRange = partition.timeRange | ||
|
||
let beginning = timeRange.beginning | ||
let `end` = timeRange.`end` | ||
|
||
if beginning <= targetMoment and targetMoment < `end`: | ||
return ok(partition) | ||
|
||
return err("Couldn't find a partition table for given time: " & $targetMoment) | ||
|
||
proc getNewestPartition*(self: PartitionManager): Result[Partition, string] = | ||
if self.partitions.len == 0: | ||
return err("there are no partitions allocated") | ||
|
||
let newestPartition = self.partitions.peekLast | ||
return ok(newestPartition) | ||
|
||
proc getOldestPartition*(self: PartitionManager): Result[Partition, string] = | ||
if self.partitions.len == 0: | ||
return err("there are no partitions allocated") | ||
|
||
let oldestPartition = self.partitions.peekFirst | ||
return ok(oldestPartition) | ||
|
||
proc addPartitionInfo*(self: PartitionManager, | ||
partitionName: string, | ||
beginning: int64, | ||
`end`: int64) = | ||
## The given partition range has seconds resolution. | ||
## We just store information of the new added partition merely to keep track of it. | ||
let partitionInfo = Partition(name: partitionName, timeRange: (beginning, `end`)) | ||
trace "Adding partition info" | ||
self.partitions.addLast(partitionInfo) | ||
|
||
proc removeOldestPartitionName*(self: PartitionManager) = | ||
## Simply removed the partition from the tracked/known partitions queue. | ||
## Just remove it and ignore it. | ||
discard self.partitions.popFirst() | ||
|
||
proc isEmpty*(self: PartitionManager): bool = | ||
return self.partitions.len == 0 | ||
|
||
proc getLastMoment*(partition: Partition): int64 = | ||
## Considering the time range covered by the partition, this | ||
## returns the `end` time (number of seconds since epoch) of such range. | ||
let lastTimeInSec = partition.timeRange.`end` | ||
return lastTimeInSec | ||
|
||
proc containsMoment*(partition: Partition, time: int64): bool = | ||
## Returns true if the given moment is contained within the partition window, | ||
## 'false' otherwise. | ||
## time - number of seconds since epoch | ||
if partition.timeRange.beginning <= time and | ||
time < partition.timeRange.`end`: | ||
return true | ||
|
||
return false | ||
|
||
proc getName*(partition: Partition): string = | ||
return partition.name | ||
|
||
func `==`*(a, b: Partition): bool {.inline.} = | ||
return a.name == b.name | ||
|
Oops, something went wrong.