2021-01-06 09:35:05 +00:00
|
|
|
## Contains types and utilities for pagination.
|
2021-07-22 08:43:41 +00:00
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
2022-02-17 10:00:45 +00:00
|
|
|
import
|
2022-07-25 11:01:37 +00:00
|
|
|
stew/byteutils,
|
|
|
|
nimcrypto
|
|
|
|
import
|
|
|
|
../protocol/waku_message,
|
|
|
|
./time
|
2022-02-17 10:00:45 +00:00
|
|
|
|
2021-01-06 09:35:05 +00:00
|
|
|
|
2022-07-25 11:01:37 +00:00
|
|
|
type Index* = object
|
|
|
|
## This type contains the description of an Index used in the pagination of WakuMessages
|
|
|
|
digest*: MDigest[256] # calculated over payload and content topic
|
|
|
|
receiverTime*: Timestamp
|
|
|
|
senderTime*: Timestamp # the time at which the message is generated
|
|
|
|
pubsubTopic*: string
|
|
|
|
|
|
|
|
|
|
|
|
proc compute*(T: type Index, msg: WakuMessage, receivedTime: Timestamp, pubsubTopic: string): T =
|
|
|
|
## Takes a WakuMessage with received timestamp and returns its Index.
|
|
|
|
## Received timestamp will default to system time if not provided.
|
|
|
|
|
|
|
|
let
|
|
|
|
contentTopic = toBytes(msg.contentTopic)
|
|
|
|
payload = msg.payload
|
|
|
|
senderTime = msg.timestamp
|
|
|
|
|
|
|
|
var ctx: sha256
|
|
|
|
ctx.init()
|
|
|
|
ctx.update(contentTopic)
|
|
|
|
ctx.update(payload)
|
|
|
|
let digest = ctx.finish() # computes the hash
|
|
|
|
ctx.clear()
|
|
|
|
|
|
|
|
Index(
|
|
|
|
digest:digest,
|
|
|
|
receiverTime: receivedTime,
|
|
|
|
senderTime: senderTime,
|
|
|
|
pubsubTopic: pubsubTopic
|
|
|
|
)
|
2022-02-17 10:00:45 +00:00
|
|
|
|
|
|
|
proc `==`*(x, y: Index): bool =
|
2022-02-28 16:29:01 +00:00
|
|
|
## receiverTime plays no role in index equality
|
|
|
|
(x.senderTime == y.senderTime) and
|
|
|
|
(x.digest == y.digest) and
|
|
|
|
(x.pubsubTopic == y.pubsubTopic)
|
2022-02-17 10:00:45 +00:00
|
|
|
|
|
|
|
proc cmp*(x, y: Index): int =
|
|
|
|
## compares x and y
|
|
|
|
## returns 0 if they are equal
|
|
|
|
## returns -1 if x < y
|
|
|
|
## returns 1 if x > y
|
2022-02-28 16:29:01 +00:00
|
|
|
##
|
|
|
|
## Default sorting order priority is:
|
|
|
|
## 1. senderTimestamp
|
|
|
|
## 2. receiverTimestamp (a fallback only if senderTimestamp unset on either side, and all other fields unequal)
|
|
|
|
## 3. message digest
|
|
|
|
## 4. pubsubTopic
|
|
|
|
|
|
|
|
if x == y:
|
|
|
|
# Quick exit ensures receiver time does not affect index equality
|
|
|
|
return 0
|
2022-02-17 10:00:45 +00:00
|
|
|
|
|
|
|
# Timestamp has a higher priority for comparison
|
2022-02-28 16:29:01 +00:00
|
|
|
let
|
|
|
|
# Use receiverTime where senderTime is unset
|
|
|
|
xTimestamp = if x.senderTime == 0: x.receiverTime
|
|
|
|
else: x.senderTime
|
|
|
|
yTimestamp = if y.senderTime == 0: y.receiverTime
|
|
|
|
else: y.senderTime
|
|
|
|
|
|
|
|
let timecmp = cmp(xTimestamp, yTimestamp)
|
2022-02-17 10:00:45 +00:00
|
|
|
if timecmp != 0:
|
|
|
|
return timecmp
|
|
|
|
|
2022-02-28 16:29:01 +00:00
|
|
|
# Continue only when timestamps are equal
|
|
|
|
let digestcmp = cmp(x.digest.data, y.digest.data)
|
|
|
|
if digestcmp != 0:
|
|
|
|
return digestcmp
|
|
|
|
|
|
|
|
return cmp(x.pubsubTopic, y.pubsubTopic)
|
2022-07-25 11:01:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
PagingDirection* {.pure.} = enum
|
|
|
|
## PagingDirection determines the direction of pagination
|
|
|
|
BACKWARD = uint32(0)
|
|
|
|
FORWARD = uint32(1)
|
|
|
|
|
|
|
|
PagingInfo* = object
|
|
|
|
## This type holds the information needed for the pagination
|
|
|
|
pageSize*: uint64
|
|
|
|
cursor*: Index
|
|
|
|
direction*: PagingDirection
|