Skip to content

Commit 1c86443

Browse files
generic refactor to make the code more aligned to logos-delivery style
1 parent 6f49a97 commit 1c86443

23 files changed

Lines changed: 413 additions & 297 deletions

sds.nim

Lines changed: 26 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
import std/[times, locks, tables, sets, options]
22
import chronos, results, chronicles
3-
import sds/[message, protobuf, sds_utils, rolling_bloom_filter]
3+
import sds/[types, protobuf, sds_utils, rolling_bloom_filter]
44

5-
export message, protobuf, sds_utils, rolling_bloom_filter
5+
export types, protobuf, sds_utils, rolling_bloom_filter
66

77
proc newReliabilityManager*(
88
config: ReliabilityConfig = defaultConfig()
99
): Result[ReliabilityManager, ReliabilityError] =
1010
## Creates a new multi-channel ReliabilityManager.
11-
##
12-
## Parameters:
13-
## - config: Configuration options for the ReliabilityManager. If not provided, default configuration is used.
14-
##
15-
## Returns:
16-
## A Result containing either a new ReliabilityManager instance or an error.
1711
try:
18-
let rm = ReliabilityManager(
19-
channels: initTable[SdsChannelID, ChannelContext](), config: config
20-
)
21-
initLock(rm.lock)
12+
let rm = ReliabilityManager.new(config)
2213
return ok(rm)
2314
except Exception:
2415
error "Failed to create ReliabilityManager", msg = getCurrentExceptionMsg()
@@ -38,22 +29,17 @@ proc isAcknowledged*(
3829
false
3930

4031
proc reviewAckStatus(rm: ReliabilityManager, msg: SdsMessage) {.gcsafe.} =
41-
# Parse bloom filter
4232
var rbf: Option[RollingBloomFilter]
4333
if msg.bloomFilter.len > 0:
4434
let bfResult = deserializeBloomFilter(msg.bloomFilter)
4535
if bfResult.isOk():
36+
let bf = bfResult.get()
4637
rbf = some(
47-
RollingBloomFilter(
48-
filter: bfResult.get(),
49-
capacity: bfResult.get().capacity,
50-
minCapacity: (
51-
bfResult.get().capacity.float * (100 - CapacityFlexPercent).float / 100.0
52-
).int,
53-
maxCapacity: (
54-
bfResult.get().capacity.float * (100 + CapacityFlexPercent).float / 100.0
55-
).int,
56-
messages: @[],
38+
RollingBloomFilter.init(
39+
filter = bf,
40+
capacity = bf.capacity,
41+
minCapacity = (bf.capacity.float * (100 - CapacityFlexPercent).float / 100.0).int,
42+
maxCapacity = (bf.capacity.float * (100 + CapacityFlexPercent).float / 100.0).int,
5743
)
5844
)
5945
else:
@@ -66,7 +52,6 @@ proc reviewAckStatus(rm: ReliabilityManager, msg: SdsMessage) {.gcsafe.} =
6652
return
6753

6854
let channel = rm.channels[msg.channelId]
69-
# Keep track of indices to delete
7055
var toDelete: seq[int] = @[]
7156
var i = 0
7257

@@ -78,7 +63,7 @@ proc reviewAckStatus(rm: ReliabilityManager, msg: SdsMessage) {.gcsafe.} =
7863
toDelete.add(i)
7964
inc i
8065

81-
for i in countdown(toDelete.high, 0): # Delete in reverse order to maintain indices
66+
for i in countdown(toDelete.high, 0):
8267
channel.outgoingBuffer.delete(toDelete[i])
8368

8469
proc wrapOutgoingMessage*(
@@ -88,14 +73,6 @@ proc wrapOutgoingMessage*(
8873
channelId: SdsChannelID,
8974
): Result[seq[byte], ReliabilityError] =
9075
## Wraps an outgoing message with reliability metadata.
91-
##
92-
## Parameters:
93-
## - message: The content of the message to be sent.
94-
## - messageId: Unique identifier for the message
95-
## - channelId: Identifier for the channel this message belongs to.
96-
##
97-
## Returns:
98-
## A Result containing either wrapped message bytes or an error.
9976
if message.len == 0:
10077
return err(ReliabilityError.reInvalidArgument)
10178
if message.len > MaxMessageSize:
@@ -111,20 +88,19 @@ proc wrapOutgoingMessage*(
11188
error "Failed to serialize bloom filter", channelId = channelId
11289
return err(ReliabilityError.reSerializationError)
11390

114-
let msg = SdsMessage(
115-
messageId: messageId,
116-
lamportTimestamp: channel.lamportTimestamp,
117-
causalHistory: rm.getRecentHistoryEntries(rm.config.maxCausalHistory, channelId),
118-
channelId: channelId,
119-
content: message,
120-
bloomFilter: bfResult.get(),
91+
let msg = SdsMessage.init(
92+
messageId = messageId,
93+
lamportTimestamp = channel.lamportTimestamp,
94+
causalHistory = rm.getRecentHistoryEntries(rm.config.maxCausalHistory, channelId),
95+
channelId = channelId,
96+
content = message,
97+
bloomFilter = bfResult.get(),
12198
)
12299

123100
channel.outgoingBuffer.add(
124-
UnacknowledgedMessage(message: msg, sendTime: getTime(), resendAttempts: 0)
101+
UnacknowledgedMessage.init(message = msg, sendTime = getTime(), resendAttempts = 0)
125102
)
126103

127-
# Add to causal history and bloom filter
128104
channel.bloomFilter.add(msg.messageId)
129105
rm.addToHistory(msg.messageId, channelId)
130106

@@ -147,7 +123,6 @@ proc processIncomingBuffer(rm: ReliabilityManager, channelId: SdsChannelID) {.gc
147123
var processed = initHashSet[SdsMessageID]()
148124
var readyToProcess = newSeq[SdsMessageID]()
149125

150-
# Find initially ready messages
151126
for msgId, entry in channel.incomingBuffer:
152127
if entry.missingDeps.len == 0:
153128
readyToProcess.add(msgId)
@@ -163,15 +138,13 @@ proc processIncomingBuffer(rm: ReliabilityManager, channelId: SdsChannelID) {.gc
163138
rm.onMessageReady(msgId, channelId)
164139
processed.incl(msgId)
165140

166-
# Update dependencies for remaining messages
167141
for remainingId, entry in channel.incomingBuffer:
168142
if remainingId notin processed:
169143
if msgId in entry.missingDeps:
170144
channel.incomingBuffer[remainingId].missingDeps.excl(msgId)
171145
if channel.incomingBuffer[remainingId].missingDeps.len == 0:
172146
readyToProcess.add(remainingId)
173147

174-
# Remove processed messages
175148
for msgId in processed:
176149
channel.incomingBuffer.del(msgId)
177150

@@ -182,12 +155,6 @@ proc unwrapReceivedMessage*(
182155
ReliabilityError,
183156
] =
184157
## Unwraps a received message and processes its reliability metadata.
185-
##
186-
## Parameters:
187-
## - message: The received message bytes
188-
##
189-
## Returns:
190-
## A Result containing either tuple of (processed message, missing dependencies, channel ID) or an error.
191158
try:
192159
let channelId = extractChannelId(message).valueOr:
193160
return err(ReliabilityError.reDeserializationError)
@@ -203,7 +170,6 @@ proc unwrapReceivedMessage*(
203170
channel.bloomFilter.add(msg.messageId)
204171

205172
rm.updateLamportTimestamp(msg.lamportTimestamp, channelId)
206-
# Review ACK status for outgoing messages
207173
rm.reviewAckStatus(msg)
208174

209175
var missingDeps = rm.checkDependencies(msg.causalHistory, channelId)
@@ -214,19 +180,20 @@ proc unwrapReceivedMessage*(
214180
if msgId in msg.causalHistory.getMessageIds():
215181
depsInBuffer = true
216182
break
217-
# Check if any dependencies are still in incoming buffer
218183
if depsInBuffer:
219184
channel.incomingBuffer[msg.messageId] =
220-
IncomingMessage(message: msg, missingDeps: initHashSet[SdsMessageID]())
185+
IncomingMessage.init(message = msg, missingDeps = initHashSet[SdsMessageID]())
221186
else:
222-
# All dependencies met, add to history
223187
rm.addToHistory(msg.messageId, channelId)
224188
rm.processIncomingBuffer(channelId)
225189
if not rm.onMessageReady.isNil():
226190
rm.onMessageReady(msg.messageId, channelId)
227191
else:
228192
channel.incomingBuffer[msg.messageId] =
229-
IncomingMessage(message: msg, missingDeps: missingDeps.getMessageIds().toHashSet())
193+
IncomingMessage.init(
194+
message = msg,
195+
missingDeps = missingDeps.getMessageIds().toHashSet(),
196+
)
230197
if not rm.onMissingDependencies.isNil():
231198
rm.onMissingDependencies(msg.messageId, missingDeps, channelId)
232199

@@ -239,13 +206,6 @@ proc markDependenciesMet*(
239206
rm: ReliabilityManager, messageIds: seq[SdsMessageID], channelId: SdsChannelID
240207
): Result[void, ReliabilityError] =
241208
## Marks the specified message dependencies as met.
242-
##
243-
## Parameters:
244-
## - messageIds: A sequence of message IDs to mark as met.
245-
## - channelId: Identifier for the channel.
246-
##
247-
## Returns:
248-
## A Result indicating success or an error.
249209
try:
250210
if channelId notin rm.channels:
251211
return err(ReliabilityError.reInvalidArgument)
@@ -273,16 +233,9 @@ proc setCallbacks*(
273233
onMessageSent: MessageSentCallback,
274234
onMissingDependencies: MissingDependenciesCallback,
275235
onPeriodicSync: PeriodicSyncCallback = nil,
276-
onRetrievalHint: RetrievalHintProvider = nil
236+
onRetrievalHint: RetrievalHintProvider = nil,
277237
) =
278238
## Sets the callback functions for various events in the ReliabilityManager.
279-
##
280-
## Parameters:
281-
## - onMessageReady: Callback function called when a message is ready to be processed.
282-
## - onMessageSent: Callback function called when a message is confirmed as sent.
283-
## - onMissingDependencies: Callback function called when a message has missing dependencies.
284-
## - onPeriodicSync: Callback function called to notify about periodic sync
285-
## - onRetrievalHint: Callback function called to get a retrieval hint for a message ID.
286239
withLock rm.lock:
287240
rm.onMessageReady = onMessageReady
288241
rm.onMessageSent = onMessageSent
@@ -293,7 +246,6 @@ proc setCallbacks*(
293246
proc checkUnacknowledgedMessages(
294247
rm: ReliabilityManager, channelId: SdsChannelID
295248
) {.gcsafe.} =
296-
## Checks and processes unacknowledged messages in the outgoing buffer.
297249
withLock rm.lock:
298250
if channelId notin rm.channels:
299251
error "Channel does not exist", channelId = channelId
@@ -322,7 +274,6 @@ proc checkUnacknowledgedMessages(
322274
proc periodicBufferSweep(
323275
rm: ReliabilityManager
324276
) {.async: (raises: [CancelledError]), gcsafe.} =
325-
## Periodically sweeps the buffer to clean up and check unacknowledged messages.
326277
while true:
327278
try:
328279
for channelId, channel in rm.channels:
@@ -340,7 +291,6 @@ proc periodicBufferSweep(
340291
proc periodicSyncMessage(
341292
rm: ReliabilityManager
342293
) {.async: (raises: [CancelledError]), gcsafe.} =
343-
## Periodically notifies to send a sync message to maintain connectivity.
344294
while true:
345295
try:
346296
if not rm.onPeriodicSync.isNil():
@@ -351,25 +301,20 @@ proc periodicSyncMessage(
351301

352302
proc startPeriodicTasks*(rm: ReliabilityManager) =
353303
## Starts the periodic tasks for buffer sweeping and sync message sending.
354-
##
355-
## This procedure should be called after creating a ReliabilityManager to enable automatic maintenance.
356304
asyncSpawn rm.periodicBufferSweep()
357305
asyncSpawn rm.periodicSyncMessage()
358306

359307
proc resetReliabilityManager*(rm: ReliabilityManager): Result[void, ReliabilityError] =
360308
## Resets the ReliabilityManager to its initial state.
361-
##
362-
## This procedure clears all buffers and resets the Lamport timestamp.
363309
withLock rm.lock:
364310
try:
365311
for channelId, channel in rm.channels:
366312
channel.lamportTimestamp = 0
367313
channel.messageHistory.setLen(0)
368314
channel.outgoingBuffer.setLen(0)
369315
channel.incomingBuffer.clear()
370-
channel.bloomFilter = newRollingBloomFilter(
371-
rm.config.bloomFilterCapacity, rm.config.bloomFilterErrorRate
372-
)
316+
channel.bloomFilter =
317+
RollingBloomFilter.init(rm.config.bloomFilterCapacity, rm.config.bloomFilterErrorRate)
373318
rm.channels.clear()
374319
return ok()
375320
except Exception:

sds/bloom.nim

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@ import hashes
33
import strutils
44
import results
55
import private/probabilities
6-
7-
type BloomFilter* = object
8-
capacity*: int
9-
errorRate*: float
10-
kHashes*: int
11-
mBits*: int
12-
intArray*: seq[int]
6+
import ./types/bloom_filter
7+
export bloom_filter
138

149
{.push overflowChecks: off.} # Turn off overflow checks for hashing operations
1510

@@ -21,12 +16,6 @@ proc hashN(item: string, n: int, maxValue: int): int =
2116
hashA = abs(hash(item)) mod maxValue # Use abs to handle negative hashes
2217
hashB = abs(hash(item & " b")) mod maxValue # string concatenation
2318
abs((hashA + n * hashB)) mod maxValue
24-
# # Use bit rotation for second hash instead of string concatenation if speed if preferred over FP-rate
25-
# # Rotate left by 21 bits (lower the rotation, higher the speed but higher the FP-rate too)
26-
# hashB = abs(
27-
# ((h shl 21) or (h shr (sizeof(int) * 8 - 21)))
28-
# ) mod maxValue
29-
# abs((hashA + n.int64 * hashB)) mod maxValue
3019

3120
{.pop.}
3221

@@ -80,12 +69,12 @@ proc initializeBloomFilter*(
8069
mInts = 1 + mBits div (sizeof(int) * 8)
8170

8271
ok(
83-
BloomFilter(
84-
capacity: capacity,
85-
errorRate: errorRate,
86-
kHashes: kHashes,
87-
mBits: mBits,
88-
intArray: newSeq[int](mInts),
72+
BloomFilter.init(
73+
capacity = capacity,
74+
errorRate = errorRate,
75+
kHashes = kHashes,
76+
mBits = mBits,
77+
intArray = newSeq[int](mInts),
8978
)
9079
)
9180

sds/message.nim

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,14 @@
1-
import std/[times, sets]
2-
3-
type
4-
SdsMessageID* = string
5-
SdsChannelID* = string
6-
7-
HistoryEntry* = object
8-
messageId*: SdsMessageID
9-
retrievalHint*: seq[byte] ## Optional hint for efficient retrieval (e.g., Waku message hash)
10-
11-
SdsMessage* = object
12-
messageId*: SdsMessageID
13-
lamportTimestamp*: int64
14-
causalHistory*: seq[HistoryEntry]
15-
channelId*: SdsChannelID
16-
content*: seq[byte]
17-
bloomFilter*: seq[byte]
18-
19-
UnacknowledgedMessage* = object
20-
message*: SdsMessage
21-
sendTime*: Time
22-
resendAttempts*: int
23-
24-
IncomingMessage* = object
25-
message*: SdsMessage
26-
missingDeps*: HashSet[SdsMessageID]
27-
28-
const
29-
DefaultMaxMessageHistory* = 1000
30-
DefaultMaxCausalHistory* = 10
31-
DefaultResendInterval* = initDuration(seconds = 60)
32-
DefaultMaxResendAttempts* = 5
33-
DefaultSyncMessageInterval* = initDuration(seconds = 30)
34-
DefaultBufferSweepInterval* = initDuration(seconds = 60)
35-
MaxMessageSize* = 1024 * 1024 # 1 MB
1+
import ./types/sds_message_id
2+
import ./types/history_entry
3+
import ./types/sds_message
4+
import ./types/unacknowledged_message
5+
import ./types/incoming_message
6+
import ./types/reliability_config
7+
8+
export
9+
sds_message_id,
10+
history_entry,
11+
sds_message,
12+
unacknowledged_message,
13+
incoming_message,
14+
reliability_config

0 commit comments

Comments
 (0)