@peerbit/native-backbone 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wasm/native_backbone.d.ts +64 -64
- package/dist/wasm/native_backbone.js +3 -0
- package/dist/wasm/native_backbone_bg.wasm +0 -0
- package/dist/wasm/native_backbone_bg.wasm.d.ts +64 -64
- package/package.json +1 -1
- package/src/append_tx/committed_latest.rs +390 -317
- package/src/append_tx/committed_no_next.rs +66 -64
- package/src/append_tx/facts.rs +213 -147
- package/src/append_tx/mod.rs +160 -58
- package/src/append_tx/storage.rs +52 -28
- package/src/coordinates.rs +135 -44
- package/src/documents.rs +340 -100
- package/src/error.rs +244 -0
- package/src/js_interop.rs +230 -90
- package/src/lib.rs +4 -0
- package/src/raw_receive.rs +182 -107
- package/src/shared_log_plan.rs +65 -23
- package/src/sync_send.rs +19 -3
- package/src/time.rs +14 -0
- package/src/wire_sync.rs +147 -36
package/src/append_tx/storage.rs
CHANGED
|
@@ -6,6 +6,7 @@ use crate::append_tx::coordinate_plan_to_row;
|
|
|
6
6
|
use crate::documents::{
|
|
7
7
|
document_context_facts_to_row, document_index_append_commit, DocumentIndexAppendCommit,
|
|
8
8
|
};
|
|
9
|
+
use crate::error::BackboneError;
|
|
9
10
|
use crate::js_interop::{
|
|
10
11
|
array_from_value, bytes_field, string_field, strings_from_array, strings_to_array,
|
|
11
12
|
trim_hashes_vec,
|
|
@@ -13,6 +14,18 @@ use crate::js_interop::{
|
|
|
13
14
|
use crate::shared_log_plan::leader_samples_to_optional_rows;
|
|
14
15
|
use crate::NativePeerbitBackbone;
|
|
15
16
|
|
|
17
|
+
/// Forward a JsValue error from an untyped log-rust wrapper without altering
|
|
18
|
+
/// its message. These wrappers construct every error via `JsValue::from_str`,
|
|
19
|
+
/// so `as_string()` recovers the exact string the wrapper would have thrown;
|
|
20
|
+
/// the fallback only guards the theoretically-non-string case.
|
|
21
|
+
fn js_wrapper_error(error: JsValue) -> BackboneError {
|
|
22
|
+
BackboneError::Message(
|
|
23
|
+
error
|
|
24
|
+
.as_string()
|
|
25
|
+
.unwrap_or_else(|| "Expected string array".to_string()),
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
#[wasm_bindgen]
|
|
17
30
|
impl NativePeerbitBackbone {
|
|
18
31
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -81,7 +94,7 @@ impl NativePeerbitBackbone {
|
|
|
81
94
|
self_replicating: bool,
|
|
82
95
|
resolve_trimmed_entries: bool,
|
|
83
96
|
) -> Result<Array, JsValue> {
|
|
84
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
97
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
85
98
|
wall_time,
|
|
86
99
|
logical,
|
|
87
100
|
gid,
|
|
@@ -98,7 +111,7 @@ impl NativePeerbitBackbone {
|
|
|
98
111
|
None,
|
|
99
112
|
false,
|
|
100
113
|
None,
|
|
101
|
-
)
|
|
114
|
+
)?)
|
|
102
115
|
}
|
|
103
116
|
|
|
104
117
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -118,7 +131,7 @@ impl NativePeerbitBackbone {
|
|
|
118
131
|
resolve_trimmed_entries: bool,
|
|
119
132
|
trim_length_to: usize,
|
|
120
133
|
) -> Result<Array, JsValue> {
|
|
121
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
134
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
122
135
|
wall_time,
|
|
123
136
|
logical,
|
|
124
137
|
gid,
|
|
@@ -135,7 +148,7 @@ impl NativePeerbitBackbone {
|
|
|
135
148
|
Some(trim_length_to),
|
|
136
149
|
false,
|
|
137
150
|
None,
|
|
138
|
-
)
|
|
151
|
+
)?)
|
|
139
152
|
}
|
|
140
153
|
|
|
141
154
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -162,7 +175,7 @@ impl NativePeerbitBackbone {
|
|
|
162
175
|
document_projection_encoded_document: JsValue,
|
|
163
176
|
document_projection_signer: JsValue,
|
|
164
177
|
) -> Result<Array, JsValue> {
|
|
165
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
178
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
166
179
|
wall_time,
|
|
167
180
|
logical,
|
|
168
181
|
gid,
|
|
@@ -188,7 +201,7 @@ impl NativePeerbitBackbone {
|
|
|
188
201
|
document_projection_encoded_document,
|
|
189
202
|
document_projection_signer,
|
|
190
203
|
)?),
|
|
191
|
-
)
|
|
204
|
+
)?)
|
|
192
205
|
}
|
|
193
206
|
|
|
194
207
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -216,7 +229,7 @@ impl NativePeerbitBackbone {
|
|
|
216
229
|
document_projection_signer: JsValue,
|
|
217
230
|
trim_length_to: usize,
|
|
218
231
|
) -> Result<Array, JsValue> {
|
|
219
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
232
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
220
233
|
wall_time,
|
|
221
234
|
logical,
|
|
222
235
|
gid,
|
|
@@ -242,7 +255,7 @@ impl NativePeerbitBackbone {
|
|
|
242
255
|
document_projection_encoded_document,
|
|
243
256
|
document_projection_signer,
|
|
244
257
|
)?),
|
|
245
|
-
)
|
|
258
|
+
)?)
|
|
246
259
|
}
|
|
247
260
|
|
|
248
261
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -262,7 +275,7 @@ impl NativePeerbitBackbone {
|
|
|
262
275
|
self_replicating: bool,
|
|
263
276
|
resolve_trimmed_entries: bool,
|
|
264
277
|
) -> Result<Array, JsValue> {
|
|
265
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
278
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
266
279
|
wall_time,
|
|
267
280
|
logical,
|
|
268
281
|
gid,
|
|
@@ -279,7 +292,7 @@ impl NativePeerbitBackbone {
|
|
|
279
292
|
None,
|
|
280
293
|
false,
|
|
281
294
|
None,
|
|
282
|
-
)
|
|
295
|
+
)?)
|
|
283
296
|
}
|
|
284
297
|
|
|
285
298
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -300,7 +313,7 @@ impl NativePeerbitBackbone {
|
|
|
300
313
|
resolve_trimmed_entries: bool,
|
|
301
314
|
trim_length_to: usize,
|
|
302
315
|
) -> Result<Array, JsValue> {
|
|
303
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
316
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
304
317
|
wall_time,
|
|
305
318
|
logical,
|
|
306
319
|
gid,
|
|
@@ -317,7 +330,7 @@ impl NativePeerbitBackbone {
|
|
|
317
330
|
Some(trim_length_to),
|
|
318
331
|
false,
|
|
319
332
|
None,
|
|
320
|
-
)
|
|
333
|
+
)?)
|
|
321
334
|
}
|
|
322
335
|
|
|
323
336
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -345,7 +358,7 @@ impl NativePeerbitBackbone {
|
|
|
345
358
|
document_projection_encoded_document: JsValue,
|
|
346
359
|
document_projection_signer: JsValue,
|
|
347
360
|
) -> Result<Array, JsValue> {
|
|
348
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
361
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
349
362
|
wall_time,
|
|
350
363
|
logical,
|
|
351
364
|
gid,
|
|
@@ -371,7 +384,7 @@ impl NativePeerbitBackbone {
|
|
|
371
384
|
document_projection_encoded_document,
|
|
372
385
|
document_projection_signer,
|
|
373
386
|
)?),
|
|
374
|
-
)
|
|
387
|
+
)?)
|
|
375
388
|
}
|
|
376
389
|
|
|
377
390
|
#[allow(clippy::too_many_arguments)]
|
|
@@ -400,7 +413,7 @@ impl NativePeerbitBackbone {
|
|
|
400
413
|
document_projection_signer: JsValue,
|
|
401
414
|
trim_length_to: usize,
|
|
402
415
|
) -> Result<Array, JsValue> {
|
|
403
|
-
self.prepare_plain_storage_append_transaction_inner(
|
|
416
|
+
Ok(self.prepare_plain_storage_append_transaction_inner(
|
|
404
417
|
wall_time,
|
|
405
418
|
logical,
|
|
406
419
|
gid,
|
|
@@ -426,7 +439,7 @@ impl NativePeerbitBackbone {
|
|
|
426
439
|
document_projection_encoded_document,
|
|
427
440
|
document_projection_signer,
|
|
428
441
|
)?),
|
|
429
|
-
)
|
|
442
|
+
)?)
|
|
430
443
|
}
|
|
431
444
|
}
|
|
432
445
|
|
|
@@ -450,9 +463,9 @@ impl NativePeerbitBackbone {
|
|
|
450
463
|
trim_length_to: Option<usize>,
|
|
451
464
|
commit_blocks: bool,
|
|
452
465
|
document_index_commit: Option<DocumentIndexAppendCommit>,
|
|
453
|
-
) -> Result<Array,
|
|
466
|
+
) -> Result<Array, BackboneError> {
|
|
454
467
|
let profile_enabled = self.append_profile_enabled;
|
|
455
|
-
let storage_append_started = profile_enabled.then(
|
|
468
|
+
let storage_append_started = profile_enabled.then(crate::time::now_ms);
|
|
456
469
|
let payload_size = payload_data.length();
|
|
457
470
|
let delete_trimmed_document_heads = document_index_commit
|
|
458
471
|
.as_ref()
|
|
@@ -462,7 +475,7 @@ impl NativePeerbitBackbone {
|
|
|
462
475
|
.and_then(|commit| commit.previous_context.clone());
|
|
463
476
|
let (entry_row, trim_rows, trim_hashes, hash, digest, meta_bytes) = if commit_blocks {
|
|
464
477
|
let (meta_data, payload_data) =
|
|
465
|
-
self.copy_append_inputs_profiled(meta_data, &payload_data)
|
|
478
|
+
self.copy_append_inputs_profiled(meta_data, &payload_data)?;
|
|
466
479
|
let (entry_facts, trim_hashes, entry_row, trim_rows) = self
|
|
467
480
|
.prepare_committed_log_append_rows_profiled(
|
|
468
481
|
wall_time,
|
|
@@ -485,6 +498,13 @@ impl NativePeerbitBackbone {
|
|
|
485
498
|
)
|
|
486
499
|
} else if let Some(trim_length_to) = trim_length_to {
|
|
487
500
|
let next_hashes_array = strings_to_array(next_hashes.clone());
|
|
501
|
+
// No typed log-rust equivalent exists for the storage-facts mode
|
|
502
|
+
// (it hands the storage bytes back to JS instead of committing
|
|
503
|
+
// them to a native block store). It is the one append path with
|
|
504
|
+
// no typed core to re-point to, so its JsValue error is forwarded
|
|
505
|
+
// verbatim through BackboneError::Message, preserving whatever
|
|
506
|
+
// string the wrapper produced (the dominant reachable case is
|
|
507
|
+
// strings_from_array over the array built just above).
|
|
488
508
|
let row = self
|
|
489
509
|
.log
|
|
490
510
|
.prepare_entry_v0_plain_entry_storage_facts_trim_and_put_with_builder(
|
|
@@ -497,7 +517,8 @@ impl NativePeerbitBackbone {
|
|
|
497
517
|
meta_data,
|
|
498
518
|
payload_data,
|
|
499
519
|
trim_length_to,
|
|
500
|
-
)
|
|
520
|
+
)
|
|
521
|
+
.map_err(js_wrapper_error)?;
|
|
501
522
|
let row = array_from_value(row.into(), "native storage trim append row")?;
|
|
502
523
|
let entry_row = array_from_value(row.get(0), "native storage trim append entry row")?;
|
|
503
524
|
let trim_rows = array_from_value(row.get(1), "native storage trim append trim rows")?;
|
|
@@ -508,6 +529,8 @@ impl NativePeerbitBackbone {
|
|
|
508
529
|
(entry_row, trim_rows, trim_hashes, hash, digest, meta_bytes)
|
|
509
530
|
} else {
|
|
510
531
|
let next_hashes_array = strings_to_array(next_hashes.clone());
|
|
532
|
+
// Same untyped storage-facts wrapper seam as the trim branch
|
|
533
|
+
// above; its JsValue error is forwarded verbatim.
|
|
511
534
|
let row = self
|
|
512
535
|
.log
|
|
513
536
|
.prepare_entry_v0_plain_entry_storage_facts_and_put_with_builder(
|
|
@@ -519,7 +542,8 @@ impl NativePeerbitBackbone {
|
|
|
519
542
|
entry_type,
|
|
520
543
|
meta_data,
|
|
521
544
|
payload_data,
|
|
522
|
-
)
|
|
545
|
+
)
|
|
546
|
+
.map_err(js_wrapper_error)?;
|
|
523
547
|
let hash = string_field(&row, 1, "storage entry hash")?;
|
|
524
548
|
let digest = bytes_field(&row, 5, "storage entry hash digest")?;
|
|
525
549
|
let meta_bytes = bytes_field(&row, 4, "storage entry meta bytes")?;
|
|
@@ -529,7 +553,7 @@ impl NativePeerbitBackbone {
|
|
|
529
553
|
let hash_number = self.hash_number_profiled(&digest)?;
|
|
530
554
|
let document_hash = hash.clone();
|
|
531
555
|
let document_gid = gid.clone();
|
|
532
|
-
let coordinate_plan_started = profile_enabled.then(
|
|
556
|
+
let coordinate_plan_started = profile_enabled.then(crate::time::now_ms);
|
|
533
557
|
let coordinate_facts = commit_local_append_for_gid_compact_core(
|
|
534
558
|
&mut self.shared_log,
|
|
535
559
|
hash,
|
|
@@ -546,9 +570,9 @@ impl NativePeerbitBackbone {
|
|
|
546
570
|
true,
|
|
547
571
|
)?;
|
|
548
572
|
if let Some(started) = coordinate_plan_started {
|
|
549
|
-
self.append_profile.coordinate_plan_ms +=
|
|
573
|
+
self.append_profile.coordinate_plan_ms += crate::time::now_ms() - started;
|
|
550
574
|
}
|
|
551
|
-
let coordinate_core_started = profile_enabled.then(
|
|
575
|
+
let coordinate_core_started = profile_enabled.then(crate::time::now_ms);
|
|
552
576
|
self.commit_coordinate_core_from_compact_facts(
|
|
553
577
|
&coordinate_facts,
|
|
554
578
|
&next_hashes,
|
|
@@ -557,7 +581,7 @@ impl NativePeerbitBackbone {
|
|
|
557
581
|
meta_bytes,
|
|
558
582
|
);
|
|
559
583
|
if let Some(started) = coordinate_core_started {
|
|
560
|
-
self.append_profile.coordinate_core_ms +=
|
|
584
|
+
self.append_profile.coordinate_core_ms += crate::time::now_ms() - started;
|
|
561
585
|
}
|
|
562
586
|
let document_trimmed_heads_processed = self.commit_append_document_index_profiled(
|
|
563
587
|
document_index_commit,
|
|
@@ -570,7 +594,7 @@ impl NativePeerbitBackbone {
|
|
|
570
594
|
&trim_hashes,
|
|
571
595
|
)?;
|
|
572
596
|
|
|
573
|
-
let result_row_started = profile_enabled.then(
|
|
597
|
+
let result_row_started = profile_enabled.then(crate::time::now_ms);
|
|
574
598
|
let out = Array::new();
|
|
575
599
|
out.push(&entry_row);
|
|
576
600
|
out.push(&leader_samples_to_optional_rows(&coordinate_facts.leaders));
|
|
@@ -589,10 +613,10 @@ impl NativePeerbitBackbone {
|
|
|
589
613
|
.unwrap_or(JsValue::UNDEFINED),
|
|
590
614
|
);
|
|
591
615
|
if let Some(started) = result_row_started {
|
|
592
|
-
self.append_profile.result_row_ms +=
|
|
616
|
+
self.append_profile.result_row_ms += crate::time::now_ms() - started;
|
|
593
617
|
}
|
|
594
618
|
if let Some(started) = storage_append_started {
|
|
595
|
-
self.append_profile.storage_append_inner_ms +=
|
|
619
|
+
self.append_profile.storage_append_inner_ms += crate::time::now_ms() - started;
|
|
596
620
|
}
|
|
597
621
|
Ok(out)
|
|
598
622
|
}
|
package/src/coordinates.rs
CHANGED
|
@@ -8,14 +8,16 @@ use peerbit_indexer_core::wire::{self, WireError};
|
|
|
8
8
|
use peerbit_shared_log_rust::NativeLocalAppendCompactFacts;
|
|
9
9
|
use wasm_bindgen::prelude::*;
|
|
10
10
|
|
|
11
|
+
use crate::error::BackboneError;
|
|
11
12
|
use crate::js_interop::{
|
|
12
13
|
append_journal_delete_record, append_journal_put_record, array_from_value, bool_field,
|
|
13
|
-
clear_journal_prefix,
|
|
14
|
-
|
|
14
|
+
clear_journal_prefix, number_strings_to_array, parse_u64_string, string_field, stringish_field,
|
|
15
|
+
strings_from_array, usize_field, write_bytes, write_string,
|
|
15
16
|
};
|
|
16
17
|
use crate::shared_log_plan::coordinate_numbers_from_array;
|
|
17
18
|
use crate::NativePeerbitBackbone;
|
|
18
19
|
|
|
20
|
+
#[derive(Debug)]
|
|
19
21
|
pub(crate) struct CoordinateCoreValue {
|
|
20
22
|
pub(crate) hash: String,
|
|
21
23
|
pub(crate) gid: String,
|
|
@@ -66,8 +68,43 @@ pub(crate) fn coordinate_core_value_to_row(value: &CoordinateCoreValue) -> Array
|
|
|
66
68
|
row
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
pub(crate) fn decode_coordinate_value(bytes: &[u8]) -> Result<CoordinateCoreValue,
|
|
70
|
-
decode_coordinate_value_core(bytes)
|
|
71
|
+
pub(crate) fn decode_coordinate_value(bytes: &[u8]) -> Result<CoordinateCoreValue, BackboneError> {
|
|
72
|
+
Ok(decode_coordinate_value_core(bytes)?)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Decode a key/value snapshot and apply journal records on top, returning
|
|
76
|
+
/// the merged entries in insertion order plus the number of journal
|
|
77
|
+
/// operations applied.
|
|
78
|
+
pub(crate) fn merged_coordinate_entries(
|
|
79
|
+
snapshot: &[u8],
|
|
80
|
+
journal: &[u8],
|
|
81
|
+
) -> Result<(Vec<(String, Vec<u8>)>, usize), BackboneError> {
|
|
82
|
+
let mut entries = if snapshot.is_empty() {
|
|
83
|
+
Default::default()
|
|
84
|
+
} else {
|
|
85
|
+
decode_key_value_snapshot(snapshot)?
|
|
86
|
+
};
|
|
87
|
+
let journal_records = if journal.is_empty() {
|
|
88
|
+
Vec::new()
|
|
89
|
+
} else {
|
|
90
|
+
decode_journal(journal)?
|
|
91
|
+
};
|
|
92
|
+
let operations = journal_records.len();
|
|
93
|
+
for record in journal_records {
|
|
94
|
+
match record {
|
|
95
|
+
JournalRecord {
|
|
96
|
+
key,
|
|
97
|
+
value: Some(value),
|
|
98
|
+
..
|
|
99
|
+
} => {
|
|
100
|
+
entries.insert(key, value);
|
|
101
|
+
}
|
|
102
|
+
JournalRecord { key, .. } => {
|
|
103
|
+
entries.shift_remove(&key);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
Ok((entries.into_iter().collect(), operations))
|
|
71
108
|
}
|
|
72
109
|
|
|
73
110
|
fn decode_coordinate_value_core(bytes: &[u8]) -> Result<CoordinateCoreValue, WireError> {
|
|
@@ -178,32 +215,8 @@ impl NativePeerbitBackbone {
|
|
|
178
215
|
snapshot: Uint8Array,
|
|
179
216
|
journal: Uint8Array,
|
|
180
217
|
) -> Result<usize, JsValue> {
|
|
181
|
-
let
|
|
182
|
-
|
|
183
|
-
} else {
|
|
184
|
-
decode_key_value_snapshot(&snapshot.to_vec()).map_err(decode_error)?
|
|
185
|
-
};
|
|
186
|
-
let journal_records = if journal.length() == 0 {
|
|
187
|
-
Vec::new()
|
|
188
|
-
} else {
|
|
189
|
-
decode_journal(&journal.to_vec()).map_err(decode_error)?
|
|
190
|
-
};
|
|
191
|
-
let operations = journal_records.len();
|
|
192
|
-
for record in journal_records {
|
|
193
|
-
match record {
|
|
194
|
-
JournalRecord {
|
|
195
|
-
key,
|
|
196
|
-
value: Some(value),
|
|
197
|
-
..
|
|
198
|
-
} => {
|
|
199
|
-
entries.insert(key, value);
|
|
200
|
-
}
|
|
201
|
-
JournalRecord { key, .. } => {
|
|
202
|
-
entries.shift_remove(&key);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
218
|
+
let (entries, operations) =
|
|
219
|
+
merged_coordinate_entries(&snapshot.to_vec(), &journal.to_vec())?;
|
|
207
220
|
self.shared_log.clear_entry_coordinates();
|
|
208
221
|
self.clear_coordinate_core();
|
|
209
222
|
for (_, value) in entries {
|
|
@@ -234,7 +247,7 @@ impl NativePeerbitBackbone {
|
|
|
234
247
|
requested_replicas: usize,
|
|
235
248
|
wall_time: u64,
|
|
236
249
|
meta_bytes: Vec<u8>,
|
|
237
|
-
) -> Result<(),
|
|
250
|
+
) -> Result<(), BackboneError> {
|
|
238
251
|
let hash_number = parse_u64_string(hash_number, "coordinate hash number")?;
|
|
239
252
|
let coordinates = coordinate_numbers_from_array(coordinates)?;
|
|
240
253
|
self.put_coordinate_core(
|
|
@@ -258,7 +271,7 @@ impl NativePeerbitBackbone {
|
|
|
258
271
|
delete_hashes: Array,
|
|
259
272
|
wall_time: u64,
|
|
260
273
|
meta_bytes: Vec<u8>,
|
|
261
|
-
) -> Result<(),
|
|
274
|
+
) -> Result<(), BackboneError> {
|
|
262
275
|
let row = array_from_value(coordinate_row, "coordinate plan row")?;
|
|
263
276
|
let hash = string_field(&row, 0, "coordinate hash")?;
|
|
264
277
|
let hash_number = stringish_field(&row, 1, "coordinate hash number")?;
|
|
@@ -301,11 +314,11 @@ impl NativePeerbitBackbone {
|
|
|
301
314
|
true,
|
|
302
315
|
);
|
|
303
316
|
let profile_enabled = self.append_profile_enabled;
|
|
304
|
-
let coordinate_delete_started = profile_enabled.then(
|
|
317
|
+
let coordinate_delete_started = profile_enabled.then(crate::time::now_ms);
|
|
305
318
|
self.delete_coordinate_core_strings(next_hashes);
|
|
306
319
|
self.delete_coordinate_core_strings(delete_hashes);
|
|
307
320
|
if let Some(started) = coordinate_delete_started {
|
|
308
|
-
self.append_profile.coordinate_delete_ms +=
|
|
321
|
+
self.append_profile.coordinate_delete_ms += crate::time::now_ms() - started;
|
|
309
322
|
}
|
|
310
323
|
}
|
|
311
324
|
|
|
@@ -322,7 +335,7 @@ impl NativePeerbitBackbone {
|
|
|
322
335
|
record_journal: bool,
|
|
323
336
|
) {
|
|
324
337
|
let profile_enabled = self.append_profile_enabled;
|
|
325
|
-
let value_encode_started = profile_enabled.then(
|
|
338
|
+
let value_encode_started = profile_enabled.then(crate::time::now_ms);
|
|
326
339
|
let value = encode_coordinate_value(
|
|
327
340
|
&hash,
|
|
328
341
|
gid,
|
|
@@ -334,24 +347,24 @@ impl NativePeerbitBackbone {
|
|
|
334
347
|
&meta_bytes,
|
|
335
348
|
);
|
|
336
349
|
if let Some(started) = value_encode_started {
|
|
337
|
-
self.append_profile.coordinate_value_encode_ms +=
|
|
350
|
+
self.append_profile.coordinate_value_encode_ms += crate::time::now_ms() - started;
|
|
338
351
|
}
|
|
339
352
|
if record_journal && self.coordinate_journal_enabled {
|
|
340
|
-
let journal_started = profile_enabled.then(
|
|
353
|
+
let journal_started = profile_enabled.then(crate::time::now_ms);
|
|
341
354
|
self.push_coordinate_journal_put(&hash, &value);
|
|
342
355
|
if let Some(started) = journal_started {
|
|
343
|
-
self.append_profile.coordinate_journal_put_ms +=
|
|
356
|
+
self.append_profile.coordinate_journal_put_ms += crate::time::now_ms() - started;
|
|
344
357
|
}
|
|
345
358
|
}
|
|
346
|
-
let index_put_started = profile_enabled.then(
|
|
359
|
+
let index_put_started = profile_enabled.then(crate::time::now_ms);
|
|
347
360
|
self.coordinate_index.insert(hash.clone());
|
|
348
361
|
if let Some(started) = index_put_started {
|
|
349
|
-
self.append_profile.coordinate_index_put_ms +=
|
|
362
|
+
self.append_profile.coordinate_index_put_ms += crate::time::now_ms() - started;
|
|
350
363
|
}
|
|
351
|
-
let value_put_started = profile_enabled.then(
|
|
364
|
+
let value_put_started = profile_enabled.then(crate::time::now_ms);
|
|
352
365
|
self.coordinate_values.put(hash, value);
|
|
353
366
|
if let Some(started) = value_put_started {
|
|
354
|
-
self.append_profile.coordinate_value_put_ms +=
|
|
367
|
+
self.append_profile.coordinate_value_put_ms += crate::time::now_ms() - started;
|
|
355
368
|
}
|
|
356
369
|
}
|
|
357
370
|
|
|
@@ -373,7 +386,10 @@ impl NativePeerbitBackbone {
|
|
|
373
386
|
self.coordinate_journal_record_count += 1;
|
|
374
387
|
}
|
|
375
388
|
|
|
376
|
-
pub(crate) fn delete_coordinate_core_batch(
|
|
389
|
+
pub(crate) fn delete_coordinate_core_batch(
|
|
390
|
+
&mut self,
|
|
391
|
+
hashes: Array,
|
|
392
|
+
) -> Result<(), BackboneError> {
|
|
377
393
|
for hash in strings_from_array(hashes)? {
|
|
378
394
|
self.delete_coordinate_core(&hash);
|
|
379
395
|
}
|
|
@@ -389,7 +405,15 @@ impl NativePeerbitBackbone {
|
|
|
389
405
|
|
|
390
406
|
#[cfg(test)]
|
|
391
407
|
mod tests {
|
|
392
|
-
use super::{
|
|
408
|
+
use super::{
|
|
409
|
+
decode_coordinate_value, decode_coordinate_value_core, encode_coordinate_value,
|
|
410
|
+
merged_coordinate_entries,
|
|
411
|
+
};
|
|
412
|
+
use crate::error::BackboneError;
|
|
413
|
+
use peerbit_indexer_core::persistence::{
|
|
414
|
+
encode_journal_delete_record, encode_journal_put_record, encode_journal_record,
|
|
415
|
+
encode_key_value_snapshot, DecodeError,
|
|
416
|
+
};
|
|
393
417
|
use peerbit_indexer_core::wire::WireError;
|
|
394
418
|
|
|
395
419
|
#[test]
|
|
@@ -419,4 +443,71 @@ mod tests {
|
|
|
419
443
|
Err(WireError::Truncated("coordinate values"))
|
|
420
444
|
));
|
|
421
445
|
}
|
|
446
|
+
|
|
447
|
+
#[test]
|
|
448
|
+
fn decode_coordinate_value_reports_typed_wire_errors() {
|
|
449
|
+
let mut bytes = encode_coordinate_value("hash", "gid", 7, &[1, 2], true, 3, 11, &[9]);
|
|
450
|
+
bytes.truncate(4);
|
|
451
|
+
|
|
452
|
+
let error = decode_coordinate_value(&bytes).unwrap_err();
|
|
453
|
+
assert_eq!(
|
|
454
|
+
error,
|
|
455
|
+
BackboneError::Wire(WireError::Truncated("coordinate hash"))
|
|
456
|
+
);
|
|
457
|
+
assert_eq!(error.to_string(), "Truncated coordinate hash");
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
#[test]
|
|
461
|
+
fn merges_snapshot_entries_with_journal_records() {
|
|
462
|
+
let snapshot = encode_key_value_snapshot(
|
|
463
|
+
[
|
|
464
|
+
("a".to_string(), vec![1u8]),
|
|
465
|
+
("b".to_string(), vec![2u8]),
|
|
466
|
+
("c".to_string(), vec![3u8]),
|
|
467
|
+
]
|
|
468
|
+
.into_iter(),
|
|
469
|
+
);
|
|
470
|
+
let mut journal = encode_journal_put_record("b", &[42]);
|
|
471
|
+
journal.extend_from_slice(&encode_journal_delete_record("c"));
|
|
472
|
+
journal.extend_from_slice(&encode_journal_put_record("d", &[4]));
|
|
473
|
+
|
|
474
|
+
let (entries, operations) = merged_coordinate_entries(&snapshot, &journal).unwrap();
|
|
475
|
+
assert_eq!(operations, 3);
|
|
476
|
+
assert_eq!(
|
|
477
|
+
entries,
|
|
478
|
+
vec![
|
|
479
|
+
("a".to_string(), vec![1u8]),
|
|
480
|
+
("b".to_string(), vec![42u8]),
|
|
481
|
+
("d".to_string(), vec![4u8]),
|
|
482
|
+
]
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
let (entries, operations) = merged_coordinate_entries(&[], &[]).unwrap();
|
|
486
|
+
assert_eq!(operations, 0);
|
|
487
|
+
assert!(entries.is_empty());
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
#[test]
|
|
491
|
+
fn merged_coordinate_entries_reports_typed_decode_errors() {
|
|
492
|
+
// The rendered message must equal the `DecodeError` Display output the
|
|
493
|
+
// old `decode_error` funnel flattened into an untyped string.
|
|
494
|
+
let snapshot = encode_key_value_snapshot([("a".to_string(), vec![1u8])].into_iter());
|
|
495
|
+
let truncated = &snapshot[..snapshot.len() - 1];
|
|
496
|
+
let expected = match super::decode_key_value_snapshot(truncated) {
|
|
497
|
+
Err(error) => error,
|
|
498
|
+
Ok(_) => panic!("snapshot decode must fail"),
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
let error = merged_coordinate_entries(truncated, &[]).unwrap_err();
|
|
502
|
+
assert_eq!(error, BackboneError::Decode(expected.clone()));
|
|
503
|
+
assert_eq!(error.to_string(), expected.to_string());
|
|
504
|
+
|
|
505
|
+
let bad_journal = encode_journal_record(&[9]);
|
|
506
|
+
let error = merged_coordinate_entries(&[], &bad_journal).unwrap_err();
|
|
507
|
+
assert_eq!(
|
|
508
|
+
error,
|
|
509
|
+
BackboneError::Decode(DecodeError::InvalidOperation(9))
|
|
510
|
+
);
|
|
511
|
+
assert_eq!(error.to_string(), "invalid operation 9");
|
|
512
|
+
}
|
|
422
513
|
}
|