@feltdb/core 0.8.3 → 0.8.5
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/cli/commands.js +4 -1
- package/dist/cli/provisioning-neutrality.js +79 -0
- package/dist/collection.d.ts +43 -1
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +192 -22
- package/dist/create/create.js +25 -21
- package/dist/create/managed-account.js +11 -0
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/Cargo.lock +165 -0
- package/dist/create/server-source/Cargo.toml +9 -0
- package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
- package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
- package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
- package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
- package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
- package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
- package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
- package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
- package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
- package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
- package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
- package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
- package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
- package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
- package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
- package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
- package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
- package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
- package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
- package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
- package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
- package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
- package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
- package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
- package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
- package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
- package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
- package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
- package/dist/create/server-source/crates/feltdb/src/equality_index.rs +595 -0
- package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
- package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
- package/dist/create/server-source/crates/feltdb/src/lib.rs +1050 -117
- package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
- package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
- package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
- package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
- package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
- package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
- package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
- package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
- package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
- package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
- package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
- package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
- package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
- package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
- package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
- package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +90 -72
- package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
- package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
- package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
- package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
- package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
- package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
- package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
- package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
- package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
- package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
- package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
- package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
- package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
- package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
- package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
- package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +126 -0
- package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
- package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
- package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
- package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
- package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
- package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
- package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
- package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +305 -6
- package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
- package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
- package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
- package/dist/create/server-source/crates/feltdb/src/state_model.rs +1514 -537
- package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
- package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
- package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
- package/dist/create/server-source/crates/feltdb/src/sync.rs +12 -0
- package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
- package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
- package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
- package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
- package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
- package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
- package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
- package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
- package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +442 -0
- package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
- package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +288 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
- package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
- package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
- package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +234 -0
- package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +947 -0
- package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
- package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
- package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
- package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1032 -0
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
- package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
- package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
- package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
- package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
- package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
- package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
- package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
- package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
- package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
- package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
- package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
- package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +2 -1
- package/dist/create/server-source/crates/feltdb-server/src/audit.rs +1137 -29
- package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +800 -34
- package/dist/db.d.ts +33 -34
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +74 -20
- package/dist/deployment.d.ts +30 -0
- package/dist/deployment.d.ts.map +1 -0
- package/dist/deployment.js +130 -0
- package/dist/embedded-transaction.d.ts +22 -4
- package/dist/embedded-transaction.d.ts.map +1 -1
- package/dist/embedded-transaction.js +51 -5
- package/dist/feltdb.d.ts +14 -2
- package/dist/feltdb.d.ts.map +1 -1
- package/dist/file-db.js +1 -1
- package/dist/http-client.d.ts +14 -0
- package/dist/http-client.d.ts.map +1 -1
- package/dist/http-client.js +23 -5
- package/dist/http-db.d.ts +119 -1
- package/dist/http-db.d.ts.map +1 -1
- package/dist/http-db.js +346 -31
- package/dist/index-core.d.ts +2 -0
- package/dist/index-core.d.ts.map +1 -1
- package/dist/index-core.js +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/indexeddb-db.d.ts.map +1 -1
- package/dist/indexeddb-db.js +35 -21
- package/dist/managed-recovery.d.ts +192 -0
- package/dist/managed-recovery.d.ts.map +1 -0
- package/dist/managed-recovery.js +242 -0
- package/dist/memory-db.js +1 -1
- package/dist/studio-app/assets/{feltdb_wasm-DB8cX151.js → feltdb_wasm-DaNwCLRX.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-DnsHNv6g.wasm +0 -0
- package/dist/studio-app/assets/index-j8IlhNqJ.js +29 -0
- package/dist/studio-app/index.html +1 -1
- package/dist/transaction.d.ts +30 -0
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +41 -0
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/workload.d.ts +2 -1
- package/dist/workload.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-ClhDHp0S.wasm +0 -0
- package/dist/studio-app/assets/index-B0k4UAlI.js +0 -29
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
/// 2. Allow callers to retry safely
|
|
33
33
|
/// 3. Maintain state correctness
|
|
34
34
|
/// 4. Show measurable rejection rate with clear retry guidance
|
|
35
|
-
|
|
36
35
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
37
36
|
use feltdb::{
|
|
38
|
-
convergence::VectorClock,
|
|
37
|
+
convergence::VectorClock,
|
|
38
|
+
submission::{SubmissionManager, SubmissionMetrics},
|
|
39
39
|
transactions::{Operation, OperationCommand, OperationId, StateVersion},
|
|
40
40
|
};
|
|
41
41
|
use std::collections::HashMap;
|
|
@@ -75,7 +75,13 @@ impl SeededRng {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
fn generate_operation(
|
|
78
|
+
fn generate_operation(
|
|
79
|
+
rng: &mut SeededRng,
|
|
80
|
+
op_id: u64,
|
|
81
|
+
seq: u64,
|
|
82
|
+
node: &str,
|
|
83
|
+
client_id: usize,
|
|
84
|
+
) -> Operation {
|
|
79
85
|
let record_id = format!("rec_{}", rng.next_range(0, 99));
|
|
80
86
|
let _is_write = rng.next_f64() >= 0.7; // 70% reads, 30% writes
|
|
81
87
|
|
|
@@ -131,7 +137,7 @@ enum OutcomeType {
|
|
|
131
137
|
struct SubmissionRecord {
|
|
132
138
|
outcome_type: OutcomeType,
|
|
133
139
|
first_attempt_latency_us: u64,
|
|
134
|
-
admission_latency_us: u64,
|
|
140
|
+
admission_latency_us: u64, // Time to final accepted/rejected outcome
|
|
135
141
|
retry_attempts: usize,
|
|
136
142
|
eventually_accepted: bool,
|
|
137
143
|
}
|
|
@@ -158,7 +164,10 @@ struct ProductionAdmissionResult {
|
|
|
158
164
|
impl ProductionAdmissionResult {
|
|
159
165
|
fn from_records(records: &[SubmissionRecord], _wall_clock_ms: f64) -> Self {
|
|
160
166
|
let total = records.len();
|
|
161
|
-
let first_attempt_accepted = records
|
|
167
|
+
let first_attempt_accepted = records
|
|
168
|
+
.iter()
|
|
169
|
+
.filter(|r| r.outcome_type == OutcomeType::Accepted && r.retry_attempts == 0)
|
|
170
|
+
.count();
|
|
162
171
|
let first_attempt_rejected = total - first_attempt_accepted;
|
|
163
172
|
let eventually_accepted = records.iter().filter(|r| r.eventually_accepted).count();
|
|
164
173
|
let permanently_rejected = total - eventually_accepted;
|
|
@@ -170,7 +179,8 @@ impl ProductionAdmissionResult {
|
|
|
170
179
|
0.0
|
|
171
180
|
};
|
|
172
181
|
|
|
173
|
-
let mut first_attempt_latencies: Vec<u64> =
|
|
182
|
+
let mut first_attempt_latencies: Vec<u64> =
|
|
183
|
+
records.iter().map(|r| r.first_attempt_latency_us).collect();
|
|
174
184
|
first_attempt_latencies.sort_unstable();
|
|
175
185
|
|
|
176
186
|
let p50_first = if !first_attempt_latencies.is_empty() {
|
|
@@ -189,7 +199,8 @@ impl ProductionAdmissionResult {
|
|
|
189
199
|
0
|
|
190
200
|
};
|
|
191
201
|
|
|
192
|
-
let mut admission_latencies: Vec<u64> =
|
|
202
|
+
let mut admission_latencies: Vec<u64> =
|
|
203
|
+
records.iter().map(|r| r.admission_latency_us).collect();
|
|
193
204
|
admission_latencies.sort_unstable();
|
|
194
205
|
|
|
195
206
|
let p50_admission = if !admission_latencies.is_empty() {
|
|
@@ -332,13 +343,25 @@ fn gate_14a_production_admission_revalidation(c: &mut Criterion) {
|
|
|
332
343
|
println!("\n═════════════════════════════════════════════════════════════");
|
|
333
344
|
println!("GATE 14A REVALIDATION: PRODUCTION ADMISSION CONTRACT");
|
|
334
345
|
println!("═════════════════════════════════════════════════════════════");
|
|
335
|
-
println!(
|
|
346
|
+
println!(
|
|
347
|
+
"\nFROZEN WORKLOAD: {} ops/client, deterministic seed={}",
|
|
348
|
+
OPERATIONS_PER_CLIENT, RANDOM_SEED
|
|
349
|
+
);
|
|
336
350
|
println!("RETRY POLICY: ProductionRetryPolicy::standard() (4 attempts, 700µs budget)");
|
|
337
351
|
println!("MEASUREMENT: First-attempt vs eventual acceptance with retry metrics\n");
|
|
338
352
|
|
|
339
|
-
println!(
|
|
340
|
-
|
|
341
|
-
|
|
353
|
+
println!(
|
|
354
|
+
"{:<8} {:<12} {:<12} {:<12} {:<12} {:<12}",
|
|
355
|
+
"Writers", "1st Accept%", "Retry Amp.", "P99 1st", "P99 Admit", "Eventually"
|
|
356
|
+
);
|
|
357
|
+
println!(
|
|
358
|
+
"{:<8} {:<12} {:<12} {:<12} {:<12} {:<12}",
|
|
359
|
+
" ", " ", " ", "Attempt", "Complete", "Accepted%"
|
|
360
|
+
);
|
|
361
|
+
println!(
|
|
362
|
+
"{:-<8} {:-<12} {:-<12} {:-<12} {:-<12} {:-<12}",
|
|
363
|
+
"", "", "", "", "", ""
|
|
364
|
+
);
|
|
342
365
|
|
|
343
366
|
let mut all_verified = true;
|
|
344
367
|
|
|
@@ -374,22 +397,52 @@ fn gate_14a_production_admission_revalidation(c: &mut Criterion) {
|
|
|
374
397
|
println!("\nDetailed metrics (8-writer case):");
|
|
375
398
|
if let Some(result) = results_by_concurrency.get(&8) {
|
|
376
399
|
println!(" Operations attempted: {}", result.total_operations);
|
|
377
|
-
println!(
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
(result.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
println!(
|
|
388
|
-
|
|
400
|
+
println!(
|
|
401
|
+
" First-attempt accepted: {} ({:.1}%)",
|
|
402
|
+
result.first_attempt_accepted,
|
|
403
|
+
(result.first_attempt_accepted as f64 / result.total_operations as f64) * 100.0
|
|
404
|
+
);
|
|
405
|
+
println!(
|
|
406
|
+
" First-attempt rejected: {} ({:.1}%)",
|
|
407
|
+
result.first_attempt_rejected,
|
|
408
|
+
(result.first_attempt_rejected as f64 / result.total_operations as f64) * 100.0
|
|
409
|
+
);
|
|
410
|
+
println!(
|
|
411
|
+
" Eventually accepted: {} ({:.1}%)",
|
|
412
|
+
result.eventually_accepted,
|
|
413
|
+
(result.eventually_accepted as f64 / result.total_operations as f64) * 100.0
|
|
414
|
+
);
|
|
415
|
+
println!(
|
|
416
|
+
" Permanently rejected: {}",
|
|
417
|
+
result.permanently_rejected
|
|
418
|
+
);
|
|
419
|
+
println!(
|
|
420
|
+
" Total retry attempts: {}",
|
|
421
|
+
result.total_retry_attempts
|
|
422
|
+
);
|
|
423
|
+
println!(
|
|
424
|
+
" Retry amplification: {:.3} retries/operation",
|
|
425
|
+
result.retry_amplification
|
|
426
|
+
);
|
|
427
|
+
println!(
|
|
428
|
+
" First-attempt P50 latency: {}µs",
|
|
429
|
+
result.p50_first_attempt_latency_us
|
|
430
|
+
);
|
|
431
|
+
println!(
|
|
432
|
+
" First-attempt P99 latency: {}µs",
|
|
433
|
+
result.p99_first_attempt_latency_us
|
|
434
|
+
);
|
|
435
|
+
println!(
|
|
436
|
+
" End-to-end P99 latency: {}µs",
|
|
437
|
+
result.p99_admission_latency_us
|
|
438
|
+
);
|
|
389
439
|
}
|
|
390
440
|
|
|
391
|
-
println!("\n{}", if all_verified { "✓" } else { "✗" }
|
|
392
|
-
println!(
|
|
441
|
+
println!("\n{}", if all_verified { "✓" } else { "✗" });
|
|
442
|
+
println!(
|
|
443
|
+
"CONTRACT VERIFICATION: {}",
|
|
444
|
+
if all_verified { "PASSED" } else { "FAILED" }
|
|
445
|
+
);
|
|
393
446
|
|
|
394
447
|
if all_verified {
|
|
395
448
|
println!("\nKEY FINDINGS:");
|
|
@@ -23,13 +23,12 @@
|
|
|
23
23
|
/// - Throughput (ops/sec)
|
|
24
24
|
/// - Final state consistency check
|
|
25
25
|
/// - State hash determinism
|
|
26
|
-
|
|
27
26
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
28
27
|
use feltdb::Operation;
|
|
29
28
|
use serde_json::json;
|
|
30
|
-
use std::sync::Arc;
|
|
31
|
-
use std::time::{Instant, Duration};
|
|
32
29
|
use std::collections::HashMap;
|
|
30
|
+
use std::sync::Arc;
|
|
31
|
+
use std::time::{Duration, Instant};
|
|
33
32
|
|
|
34
33
|
// ============================================================================
|
|
35
34
|
// FROZEN WORKLOAD DEFINITION
|
|
@@ -147,11 +146,7 @@ struct AdmissionContractResult {
|
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
impl AdmissionContractResult {
|
|
150
|
-
fn new(
|
|
151
|
-
outcomes: &[OperationRecord],
|
|
152
|
-
ingested_count: usize,
|
|
153
|
-
wall_clock_ms: f64,
|
|
154
|
-
) -> Self {
|
|
149
|
+
fn new(outcomes: &[OperationRecord], ingested_count: usize, wall_clock_ms: f64) -> Self {
|
|
155
150
|
let successful = outcomes
|
|
156
151
|
.iter()
|
|
157
152
|
.filter(|r| r.outcome != OperationOutcome::Rejected)
|
|
@@ -340,12 +335,17 @@ fn gate_14a_rc2_admission_contract(c: &mut Criterion) {
|
|
|
340
335
|
println!("\n───────────────────────────────────────────────────────────────");
|
|
341
336
|
|
|
342
337
|
// Collect results indexed by [retry_budget][concurrency]
|
|
343
|
-
let mut all_results: HashMap<usize, HashMap<usize, AdmissionContractResult>> =
|
|
344
|
-
HashMap::new();
|
|
338
|
+
let mut all_results: HashMap<usize, HashMap<usize, AdmissionContractResult>> = HashMap::new();
|
|
345
339
|
|
|
346
340
|
for &retry_budget in RETRY_BUDGETS {
|
|
347
|
-
println!(
|
|
348
|
-
|
|
341
|
+
println!(
|
|
342
|
+
"\nRETRY BUDGET: {}",
|
|
343
|
+
if retry_budget == 100 {
|
|
344
|
+
"∞ (unlimited)".to_string()
|
|
345
|
+
} else {
|
|
346
|
+
retry_budget.to_string()
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
349
|
println!("┌────────────────────────────────────────────────────────────┐");
|
|
350
350
|
println!(
|
|
351
351
|
"│ {:6} │ {:8} │ {:8} │ {:7} │ {:7} │ {:7} │ Contract",
|
|
@@ -418,7 +418,10 @@ fn gate_14a_rc2_admission_contract(c: &mut Criterion) {
|
|
|
418
418
|
};
|
|
419
419
|
println!(
|
|
420
420
|
"{:15} │ {:7.1}% │ {:8} │ {:7.0} │ {:7.0}",
|
|
421
|
-
budget_label,
|
|
421
|
+
budget_label,
|
|
422
|
+
success_pct,
|
|
423
|
+
result.rejected,
|
|
424
|
+
result.p95_latency_us,
|
|
422
425
|
result.throughput_ops_per_sec
|
|
423
426
|
);
|
|
424
427
|
}
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
/// 2. Identify whether boundary is sharp (7 PASS, 8 FAIL) or probabilistic
|
|
15
15
|
/// 3. Reproduce exact failing sequence for later instrumentation
|
|
16
16
|
/// 4. Establish baseline for state-hash divergence analysis
|
|
17
|
-
|
|
18
17
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
19
18
|
use feltdb::Operation;
|
|
20
19
|
use serde_json::json;
|
|
20
|
+
use std::collections::HashMap;
|
|
21
21
|
use std::sync::Arc;
|
|
22
22
|
use std::time::Duration;
|
|
23
|
-
use std::collections::HashMap;
|
|
24
23
|
|
|
25
24
|
// ============================================================================
|
|
26
25
|
// FROZEN WORKLOAD (identical to Gate 14A)
|
|
@@ -208,7 +207,10 @@ fn gate_14a_rc_root_cause(c: &mut Criterion) {
|
|
|
208
207
|
|
|
209
208
|
println!(
|
|
210
209
|
"{:7} | {:6} | {:4} | {:4} | {:8} | {:6} | {:9}",
|
|
211
|
-
concurrency,
|
|
210
|
+
concurrency,
|
|
211
|
+
TRIALS_PER_LEVEL,
|
|
212
|
+
pass_count,
|
|
213
|
+
fail_count,
|
|
212
214
|
concurrency * OPERATIONS_PER_CLIENT,
|
|
213
215
|
concurrency * OPERATIONS_PER_CLIENT - avg_missing,
|
|
214
216
|
avg_missing
|
|
@@ -234,7 +236,10 @@ fn gate_14a_rc_root_cause(c: &mut Criterion) {
|
|
|
234
236
|
pass_level, fail_level
|
|
235
237
|
);
|
|
236
238
|
println!("\n This is a deterministic transition.");
|
|
237
|
-
println!(
|
|
239
|
+
println!(
|
|
240
|
+
" Next: Investigate why exactly {} writers exceeds capacity.",
|
|
241
|
+
fail_level
|
|
242
|
+
);
|
|
238
243
|
} else {
|
|
239
244
|
println!(" ? PROBABILISTIC BOUNDARY (failures at multiple levels)");
|
|
240
245
|
for (concurrency, pass, fail, missing) in &boundary_results {
|
|
@@ -262,7 +267,10 @@ fn gate_14a_rc_root_cause(c: &mut Criterion) {
|
|
|
262
267
|
println!(" 5. Instrument FeltDB internals to prove subsystem");
|
|
263
268
|
println!("\nCURRENT HYPOTHESIS:");
|
|
264
269
|
if let Some((_, fail_level)) = sharp_boundary {
|
|
265
|
-
println!(
|
|
270
|
+
println!(
|
|
271
|
+
" Operation buffer or lock contention reaches limit at {} writers",
|
|
272
|
+
fail_level
|
|
273
|
+
);
|
|
266
274
|
}
|
|
267
275
|
println!("═══════════════════════════════════════════════════════════\n");
|
|
268
276
|
|
|
@@ -21,14 +21,13 @@
|
|
|
21
21
|
/// ✓ Improves p99 submission latency (or acceptable tradeoff)
|
|
22
22
|
/// ✓ Reduces rejection rate
|
|
23
23
|
/// ✓ Produces identical state (state_hash match)
|
|
24
|
-
|
|
25
24
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
26
25
|
use feltdb::Operation;
|
|
27
26
|
use serde_json::json;
|
|
28
|
-
use std::sync::Arc;
|
|
29
27
|
use std::collections::VecDeque;
|
|
30
|
-
use std::time::{Instant, Duration};
|
|
31
28
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
29
|
+
use std::sync::Arc;
|
|
30
|
+
use std::time::{Duration, Instant};
|
|
32
31
|
|
|
33
32
|
// ============================================================================
|
|
34
33
|
// FROZEN WORKLOAD
|
|
@@ -396,7 +395,10 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
396
395
|
println!("═══════════════════════════════════════════════════════════════════");
|
|
397
396
|
println!("\nEXPERIMENT DESIGN:");
|
|
398
397
|
println!(" Control: Direct mutex acquisition (current)");
|
|
399
|
-
println!(
|
|
398
|
+
println!(
|
|
399
|
+
" Candidate: Bounded queue ({}) + single worker",
|
|
400
|
+
QUEUE_SIZE
|
|
401
|
+
);
|
|
400
402
|
println!("\nFROZEN WORKLOAD:");
|
|
401
403
|
println!(" Operations per client: {}", OPERATIONS_PER_CLIENT);
|
|
402
404
|
println!(" Concurrency: 1, 2, 4, 8, 16, 32, 64");
|
|
@@ -421,12 +423,10 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
421
423
|
|
|
422
424
|
for &concurrency in CONCURRENCY_LEVELS {
|
|
423
425
|
// Measure mutex (control)
|
|
424
|
-
let (mutex_metrics, mutex_hash) =
|
|
425
|
-
rt.block_on(measure_mutex_admission(concurrency));
|
|
426
|
+
let (mutex_metrics, mutex_hash) = rt.block_on(measure_mutex_admission(concurrency));
|
|
426
427
|
|
|
427
428
|
// Measure queued (candidate)
|
|
428
|
-
let (queued_metrics, queued_hash) =
|
|
429
|
-
rt.block_on(measure_queued_admission(concurrency));
|
|
429
|
+
let (queued_metrics, queued_hash) = rt.block_on(measure_queued_admission(concurrency));
|
|
430
430
|
|
|
431
431
|
// Verify state hash match
|
|
432
432
|
let hash_match = mutex_hash == queued_hash;
|
|
@@ -438,7 +438,11 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
438
438
|
mutex_metrics.p99_submission_latency_us,
|
|
439
439
|
queued_metrics.throughput_ops_per_sec,
|
|
440
440
|
queued_metrics.p99_submission_latency_us,
|
|
441
|
-
if hash_match {
|
|
441
|
+
if hash_match {
|
|
442
|
+
"✓ MATCH"
|
|
443
|
+
} else {
|
|
444
|
+
"✗ MISMATCH"
|
|
445
|
+
}
|
|
442
446
|
);
|
|
443
447
|
|
|
444
448
|
comparison_results.push((concurrency, mutex_metrics, queued_metrics, hash_match));
|
|
@@ -462,10 +466,7 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
462
466
|
* 100.0;
|
|
463
467
|
|
|
464
468
|
println!("│ At 64 writers:");
|
|
465
|
-
println!(
|
|
466
|
-
"│ Mutex: {:8.0} ops/sec",
|
|
467
|
-
mutex_m.throughput_ops_per_sec
|
|
468
|
-
);
|
|
469
|
+
println!("│ Mutex: {:8.0} ops/sec", mutex_m.throughput_ops_per_sec);
|
|
469
470
|
println!(
|
|
470
471
|
"│ Queued: {:8.0} ops/sec",
|
|
471
472
|
queued_m.throughput_ops_per_sec
|
|
@@ -478,8 +479,7 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
478
479
|
println!("\n┌─ Latency Analysis ────────────────────────────────────────┐");
|
|
479
480
|
for (concurrency, mutex_m, queued_m, _) in &comparison_results {
|
|
480
481
|
if *concurrency == 64 {
|
|
481
|
-
let p99_improvement = ((mutex_m.p99_submission_latency_us
|
|
482
|
-
as f64
|
|
482
|
+
let p99_improvement = ((mutex_m.p99_submission_latency_us as f64
|
|
483
483
|
- queued_m.p99_submission_latency_us as f64)
|
|
484
484
|
/ mutex_m.p99_submission_latency_us as f64)
|
|
485
485
|
* 100.0;
|
|
@@ -503,7 +503,10 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
503
503
|
println!("│ At 64 writers:");
|
|
504
504
|
println!("│ Mutex rejection: {:.2}%", mutex_rejection);
|
|
505
505
|
println!("│ Queued rejection: {:.2}%", queued_rejection);
|
|
506
|
-
println!(
|
|
506
|
+
println!(
|
|
507
|
+
"│ Improvement: {:.2}pp",
|
|
508
|
+
mutex_rejection - queued_rejection
|
|
509
|
+
);
|
|
507
510
|
}
|
|
508
511
|
}
|
|
509
512
|
println!("└───────────────────────────────────────────────────────────┘");
|
|
@@ -534,24 +537,40 @@ fn gate_14a_sync1_queued_prototype(c: &mut Criterion) {
|
|
|
534
537
|
|
|
535
538
|
// Check 1: Reduces contention (implied by throughput improvement at high concurrency)
|
|
536
539
|
if throughput_improvement_64 > 5.0 {
|
|
537
|
-
println!(
|
|
540
|
+
println!(
|
|
541
|
+
"✓ Reduces contention: Throughput improved by {:.1}% at 64 writers",
|
|
542
|
+
throughput_improvement_64
|
|
543
|
+
);
|
|
538
544
|
decision_points.push(true);
|
|
539
545
|
} else if throughput_improvement_64 > -5.0 {
|
|
540
|
-
println!(
|
|
546
|
+
println!(
|
|
547
|
+
"~ Contention reduction unclear: {:.1}% change at 64 writers",
|
|
548
|
+
throughput_improvement_64
|
|
549
|
+
);
|
|
541
550
|
decision_points.push(false);
|
|
542
551
|
} else {
|
|
543
|
-
println!(
|
|
552
|
+
println!(
|
|
553
|
+
"✗ Increases contention: Throughput decreased by {:.1}% at 64 writers",
|
|
554
|
+
throughput_improvement_64.abs()
|
|
555
|
+
);
|
|
544
556
|
decision_points.push(false);
|
|
545
557
|
}
|
|
546
558
|
|
|
547
559
|
// Check 2: Sustainable throughput at high concurrency
|
|
548
|
-
if let Some((_, mutex_m, queued_m, _)) = comparison_results.iter().find(|(c, _, _, _)| *c == 64)
|
|
560
|
+
if let Some((_, mutex_m, queued_m, _)) = comparison_results.iter().find(|(c, _, _, _)| *c == 64)
|
|
561
|
+
{
|
|
549
562
|
let ratio = queued_m.throughput_ops_per_sec / mutex_m.throughput_ops_per_sec;
|
|
550
563
|
if ratio > 1.0 {
|
|
551
|
-
println!(
|
|
564
|
+
println!(
|
|
565
|
+
"✓ Increases sustainable throughput: {:.2}x at 64 writers",
|
|
566
|
+
ratio
|
|
567
|
+
);
|
|
552
568
|
decision_points.push(true);
|
|
553
569
|
} else {
|
|
554
|
-
println!(
|
|
570
|
+
println!(
|
|
571
|
+
"✗ Throughput reduced or unchanged: {:.2}x at 64 writers",
|
|
572
|
+
ratio
|
|
573
|
+
);
|
|
555
574
|
decision_points.push(false);
|
|
556
575
|
}
|
|
557
576
|
}
|
|
@@ -25,12 +25,11 @@
|
|
|
25
25
|
/// Ratio = lock_wait_time / total_operation_time
|
|
26
26
|
/// If ratio is high (lock dominates) → admission architecture is bottleneck
|
|
27
27
|
/// If ratio is low (lock is cheap) → other subsystem is constrained
|
|
28
|
-
|
|
29
28
|
use criterion::{criterion_group, criterion_main, Criterion};
|
|
30
29
|
use feltdb::Operation;
|
|
31
30
|
use serde_json::json;
|
|
32
31
|
use std::sync::Arc;
|
|
33
|
-
use std::time::{
|
|
32
|
+
use std::time::{Duration, Instant};
|
|
34
33
|
|
|
35
34
|
// ============================================================================
|
|
36
35
|
// FROZEN WORKLOAD DEFINITION
|
|
@@ -140,7 +139,7 @@ struct LockStatistics {
|
|
|
140
139
|
p50_operation_latency_us: u64,
|
|
141
140
|
p95_operation_latency_us: u64,
|
|
142
141
|
p99_operation_latency_us: u64,
|
|
143
|
-
lock_wait_ratio: f64,
|
|
142
|
+
lock_wait_ratio: f64, // lock_wait_time / total_operation_time
|
|
144
143
|
critical_section_ratio: f64, // lock_hold_time / total_operation_time
|
|
145
144
|
}
|
|
146
145
|
|
|
@@ -375,26 +374,45 @@ fn gate_14a_sync_economics(c: &mut Criterion) {
|
|
|
375
374
|
}
|
|
376
375
|
|
|
377
376
|
// Average across trials
|
|
378
|
-
let avg_success: usize = trial_stats
|
|
377
|
+
let avg_success: usize = trial_stats
|
|
378
|
+
.iter()
|
|
379
|
+
.map(|s| s.successful_operations)
|
|
380
|
+
.sum::<usize>()
|
|
381
|
+
/ trial_stats.len();
|
|
382
|
+
let avg_rejected: usize = trial_stats
|
|
383
|
+
.iter()
|
|
384
|
+
.map(|s| s.rejected_operations)
|
|
385
|
+
.sum::<usize>()
|
|
379
386
|
/ trial_stats.len();
|
|
380
|
-
let
|
|
387
|
+
let avg_attempts: usize = trial_stats
|
|
388
|
+
.iter()
|
|
389
|
+
.map(|s| s.total_acquisition_attempts)
|
|
390
|
+
.sum::<usize>()
|
|
381
391
|
/ trial_stats.len();
|
|
382
|
-
let
|
|
383
|
-
trial_stats.iter().map(|s| s.
|
|
384
|
-
|
|
385
|
-
|
|
392
|
+
let avg_wait_ratio: f64 =
|
|
393
|
+
trial_stats.iter().map(|s| s.lock_wait_ratio).sum::<f64>() / trial_stats.len() as f64;
|
|
394
|
+
let avg_hold_ratio: f64 = trial_stats
|
|
395
|
+
.iter()
|
|
396
|
+
.map(|s| s.critical_section_ratio)
|
|
397
|
+
.sum::<f64>()
|
|
386
398
|
/ trial_stats.len() as f64;
|
|
387
|
-
let
|
|
399
|
+
let avg_ops_per_acq: f64 = trial_stats
|
|
400
|
+
.iter()
|
|
401
|
+
.map(|s| s.ops_per_acquisition)
|
|
402
|
+
.sum::<f64>()
|
|
388
403
|
/ trial_stats.len() as f64;
|
|
389
|
-
let
|
|
404
|
+
let avg_throughput: f64 = trial_stats
|
|
405
|
+
.iter()
|
|
406
|
+
.map(|s| s.throughput_ops_per_sec)
|
|
407
|
+
.sum::<f64>()
|
|
390
408
|
/ trial_stats.len() as f64;
|
|
391
|
-
let avg_throughput: f64 =
|
|
392
|
-
trial_stats.iter().map(|s| s.throughput_ops_per_sec).sum::<f64>()
|
|
393
|
-
/ trial_stats.len() as f64;
|
|
394
409
|
|
|
395
410
|
println!(
|
|
396
411
|
"{:8} │ {:8} │ {:8} │ {:8} │ {:5.1}% │ {:5.1}% │ {:6.2} │ {:8.0}",
|
|
397
|
-
concurrency,
|
|
412
|
+
concurrency,
|
|
413
|
+
avg_success,
|
|
414
|
+
avg_rejected,
|
|
415
|
+
avg_attempts,
|
|
398
416
|
avg_wait_ratio * 100.0,
|
|
399
417
|
avg_hold_ratio * 100.0,
|
|
400
418
|
avg_ops_per_acq,
|