@feltdb/core 0.15.0 → 0.16.0
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/agent-state.d.ts +20 -0
- package/dist/agent-state.d.ts.map +1 -1
- package/dist/agent-state.js +36 -0
- package/dist/build-identity.json +12 -4
- package/dist/cli/commands.js +187 -4
- package/dist/cli/publish-engine.js +116 -16
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +3 -0
- package/dist/create/build-identity.json +12 -4
- package/dist/create/managed-account.js +93 -35
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/Cargo.lock +6 -509
- package/dist/create/server-source/Cargo.toml +2 -13
- package/dist/create/server-source/crates/feltdb-client/Cargo.toml +1 -1
- package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -1
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +255 -12
- package/dist/create/server-source/crates/feltdb-wasm/Cargo.toml +1 -1
- package/dist/db.d.ts +11 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +15 -2
- package/dist/error-codes.d.ts +5 -0
- package/dist/error-codes.d.ts.map +1 -1
- package/dist/error-codes.js +9 -1
- package/dist/http-db.d.ts +16 -0
- package/dist/http-db.d.ts.map +1 -1
- package/dist/http-db.js +36 -6
- package/dist/managed-recovery.d.ts +6 -0
- package/dist/managed-recovery.d.ts.map +1 -1
- package/dist/managed-recovery.js +9 -0
- package/dist/studio-app/assets/{feltdb_wasm-BjM1ylL3.js → feltdb_wasm-DtybUY0q.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-DsgIUwaB.wasm +0 -0
- package/dist/studio-app/assets/index-C4OffsZl.js +37 -0
- package/dist/studio-app/index.html +1 -1
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/wasm/package.json +1 -1
- package/dist/workload.d.ts +55 -3
- package/dist/workload.d.ts.map +1 -1
- package/dist/workload.js +23 -0
- package/dist/workspace/workspace-connection.d.ts.map +1 -1
- package/dist/workspace/workspace-connection.js +14 -3
- package/package.json +1 -1
- package/dist/create/server-source/crates/feltdb/Cargo.lock +0 -175
- package/dist/create/server-source/crates/feltdb/Cargo.toml +0 -102
- package/dist/create/server-source/crates/feltdb/LICENSE +0 -21
- package/dist/create/server-source/crates/feltdb/README.md +0 -75
- package/dist/create/server-source/crates/feltdb/benches/baselines/gate-13-redux.json +0 -370
- package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +0 -589
- package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +0 -247
- package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +0 -440
- package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +0 -275
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +0 -381
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +0 -467
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +0 -489
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +0 -281
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +0 -606
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +0 -531
- package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +0 -462
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +0 -505
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +0 -484
- package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +0 -758
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +0 -421
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +0 -329
- package/dist/create/server-source/crates/feltdb/src/acceptance_tests.rs +0 -1705
- package/dist/create/server-source/crates/feltdb/src/acquisition.rs +0 -286
- package/dist/create/server-source/crates/feltdb/src/admission.rs +0 -185
- package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +0 -507
- package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +0 -539
- package/dist/create/server-source/crates/feltdb/src/agent_state.rs +0 -320
- package/dist/create/server-source/crates/feltdb/src/agent_transition_contract.rs +0 -1545
- package/dist/create/server-source/crates/feltdb/src/analytics.rs +0 -521
- package/dist/create/server-source/crates/feltdb/src/application.rs +0 -2674
- package/dist/create/server-source/crates/feltdb/src/application_runtime.rs +0 -1070
- package/dist/create/server-source/crates/feltdb/src/authority.rs +0 -479
- package/dist/create/server-source/crates/feltdb/src/authority_failover.rs +0 -847
- package/dist/create/server-source/crates/feltdb/src/authorization.rs +0 -1030
- package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +0 -1122
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority-client.rs +0 -32
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority.rs +0 -19
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +0 -1474
- package/dist/create/server-source/crates/feltdb/src/capabilities/mod.rs +0 -8
- package/dist/create/server-source/crates/feltdb/src/capabilities/search.rs +0 -418
- package/dist/create/server-source/crates/feltdb/src/capabilities/vector.rs +0 -482
- package/dist/create/server-source/crates/feltdb/src/capability.rs +0 -903
- package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +0 -263
- package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -77
- package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +0 -496
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +0 -2574
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +0 -212
- package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +0 -422
- package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +0 -445
- package/dist/create/server-source/crates/feltdb/src/content_distribution.rs +0 -465
- package/dist/create/server-source/crates/feltdb/src/convergence.rs +0 -634
- package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +0 -427
- package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +0 -376
- package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +0 -365
- package/dist/create/server-source/crates/feltdb/src/cron.rs +0 -294
- package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +0 -483
- package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +0 -477
- package/dist/create/server-source/crates/feltdb/src/distributed_tests.rs +0 -1003
- package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +0 -1334
- package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +0 -368
- package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +0 -231
- package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +0 -482
- package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +0 -203
- package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +0 -317
- package/dist/create/server-source/crates/feltdb/src/equality_index.rs +0 -595
- package/dist/create/server-source/crates/feltdb/src/execution.rs +0 -426
- package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +0 -214
- package/dist/create/server-source/crates/feltdb/src/indexing.rs +0 -776
- package/dist/create/server-source/crates/feltdb/src/lib.rs +0 -7365
- package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +0 -234
- package/dist/create/server-source/crates/feltdb/src/materialization.rs +0 -184
- package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -266
- package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +0 -310
- package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +0 -736
- package/dist/create/server-source/crates/feltdb/src/observability.rs +0 -379
- package/dist/create/server-source/crates/feltdb/src/operation.rs +0 -290
- package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +0 -439
- package/dist/create/server-source/crates/feltdb/src/operation_log.rs +0 -349
- package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +0 -332
- package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +0 -718
- package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +0 -487
- package/dist/create/server-source/crates/feltdb/src/peer_registry.rs +0 -166
- package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +0 -289
- package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +0 -566
- package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +0 -3391
- package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +0 -203
- package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +0 -261
- package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +0 -502
- package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +0 -216
- package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +0 -303
- package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +0 -323
- package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +0 -531
- package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +0 -406
- package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +0 -436
- package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +0 -387
- package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +0 -378
- package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +0 -359
- package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +0 -372
- package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +0 -404
- package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +0 -376
- package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +0 -461
- package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +0 -2125
- package/dist/create/server-source/crates/feltdb/src/production_api.rs +0 -418
- package/dist/create/server-source/crates/feltdb/src/provenance.rs +0 -207
- package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +0 -126
- package/dist/create/server-source/crates/feltdb/src/query_performance.rs +0 -218
- package/dist/create/server-source/crates/feltdb/src/read_basis.rs +0 -257
- package/dist/create/server-source/crates/feltdb/src/references.rs +0 -404
- package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +0 -401
- package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +0 -501
- package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +0 -680
- package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +0 -163
- package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +0 -133
- package/dist/create/server-source/crates/feltdb/src/routing.rs +0 -409
- package/dist/create/server-source/crates/feltdb/src/semantic_decision.rs +0 -2029
- package/dist/create/server-source/crates/feltdb/src/semantic_query.rs +0 -599
- package/dist/create/server-source/crates/feltdb/src/sharding.rs +0 -549
- package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +0 -516
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +0 -6003
- package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +0 -222
- package/dist/create/server-source/crates/feltdb/src/state_facade.rs +0 -320
- package/dist/create/server-source/crates/feltdb/src/state_hash.rs +0 -291
- package/dist/create/server-source/crates/feltdb/src/state_model.rs +0 -4158
- package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +0 -379
- package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +0 -673
- package/dist/create/server-source/crates/feltdb/src/storage.rs +0 -273
- package/dist/create/server-source/crates/feltdb/src/submission.rs +0 -471
- package/dist/create/server-source/crates/feltdb/src/sync.rs +0 -495
- package/dist/create/server-source/crates/feltdb/src/sync_contract.rs +0 -822
- package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +0 -433
- package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +0 -462
- package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +0 -965
- package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +0 -1120
- package/dist/create/server-source/crates/feltdb/src/transactions.rs +0 -643
- package/dist/create/server-source/crates/feltdb/src/trigger.rs +0 -390
- package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +0 -749
- package/dist/create/server-source/crates/feltdb/src/versioned_object_substrate.rs +0 -708
- package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +0 -1269
- package/dist/create/server-source/crates/feltdb/src/workflow.rs +0 -713
- package/dist/create/server-source/crates/feltdb/src/workflow_acceptance_tests.rs +0 -510
- package/dist/create/server-source/crates/feltdb/src/workflow_integration.rs +0 -354
- package/dist/create/server-source/crates/feltdb/src/workflow_runtime.rs +0 -594
- package/dist/create/server-source/crates/feltdb/src/workload.rs +0 -4222
- package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +0 -456
- package/dist/create/server-source/crates/feltdb/tests/agent_state_native.rs +0 -1188
- package/dist/create/server-source/crates/feltdb/tests/agent_transition_contract_conformance.rs +0 -2884
- package/dist/create/server-source/crates/feltdb/tests/authority_process.rs +0 -297
- package/dist/create/server-source/crates/feltdb/tests/authority_transaction_identity.rs +0 -534
- package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +0 -132
- package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/common/mod.rs +0 -96
- package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +0 -272
- package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +0 -467
- package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +0 -309
- package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +0 -445
- package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +0 -518
- package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +0 -392
- package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +0 -850
- package/dist/create/server-source/crates/feltdb/tests/fixtures/agent_transition_corpus.json +0 -23340
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +0 -1916
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +0 -1878
- package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +0 -1862
- package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_evidence.rs +0 -123
- package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_substrate_completion.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/local_process_ownership.rs +0 -69
- package/dist/create/server-source/crates/feltdb/tests/managed_incident_regression.rs +0 -191
- package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +0 -278
- package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +0 -234
- package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +0 -947
- package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +0 -404
- package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +0 -916
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +0 -1045
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +0 -347
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +0 -361
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +0 -330
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +0 -93
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +0 -622
- package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +0 -517
- package/dist/create/server-source/crates/feltdb/tests/production_certification.rs +0 -1153
- package/dist/create/server-source/crates/feltdb/tests/production_contract.rs +0 -771
- package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +0 -1383
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +0 -868
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +0 -221
- package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +0 -417
- package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +0 -338
- package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +0 -1039
- package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +0 -739
- package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +0 -452
- package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +0 -81
- package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +0 -438
- package/dist/create/server-source/crates/feltdb/tests/semantic_decision.rs +0 -1165
- package/dist/create/server-source/crates/feltdb/tests/semantic_query.rs +0 -767
- package/dist/create/server-source/crates/feltdb/tests/semantic_query_contract.rs +0 -363
- package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +0 -1799
- package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +0 -1316
- package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +0 -358
- package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +0 -365
- package/dist/create/server-source/crates/feltdb/tests/state_ref_authority.rs +0 -918
- package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/storage_independent_versioned_object_substrate.rs +0 -328
- package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +0 -255
- package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +0 -249
- package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +0 -994
- package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +0 -484
- package/dist/studio-app/assets/feltdb_wasm_bg-TseJn2Ax.wasm +0 -0
- package/dist/studio-app/assets/index-1wd0uKua.js +0 -30
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/// Replication Manager
|
|
2
|
-
///
|
|
3
|
-
/// Coordinates message routing and delivery between nodes in a distributed cluster.
|
|
4
|
-
/// Handles:
|
|
5
|
-
/// - Tracking pending operations and their delivery status
|
|
6
|
-
/// - Routing messages from leader to followers
|
|
7
|
-
/// - Acknowledgment tracking
|
|
8
|
-
/// - Retry logic for lost messages
|
|
9
|
-
use crate::distributed_transactions::ReplicationMessage;
|
|
10
|
-
use std::collections::{HashMap, VecDeque};
|
|
11
|
-
use std::sync::atomic::{AtomicU64, Ordering};
|
|
12
|
-
use std::sync::Arc;
|
|
13
|
-
|
|
14
|
-
/// Message delivery status
|
|
15
|
-
#[derive(Clone, Debug, PartialEq)]
|
|
16
|
-
pub enum DeliveryStatus {
|
|
17
|
-
Pending,
|
|
18
|
-
Delivered,
|
|
19
|
-
Acknowledged,
|
|
20
|
-
Failed,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/// Tracked message for replication
|
|
24
|
-
#[derive(Clone)]
|
|
25
|
-
pub struct TrackedMessage {
|
|
26
|
-
pub message: ReplicationMessage,
|
|
27
|
-
pub status: DeliveryStatus,
|
|
28
|
-
pub send_count: u64,
|
|
29
|
-
pub timestamp_ms: u64,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
impl TrackedMessage {
|
|
33
|
-
pub fn new(message: ReplicationMessage) -> Self {
|
|
34
|
-
let timestamp_ms = std::time::SystemTime::now()
|
|
35
|
-
.duration_since(std::time::UNIX_EPOCH)
|
|
36
|
-
.unwrap()
|
|
37
|
-
.as_millis() as u64;
|
|
38
|
-
|
|
39
|
-
Self {
|
|
40
|
-
message,
|
|
41
|
-
status: DeliveryStatus::Pending,
|
|
42
|
-
send_count: 0,
|
|
43
|
-
timestamp_ms,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/// Tracks pending messages to be replicated to a specific peer
|
|
49
|
-
pub struct PeerReplicationQueue {
|
|
50
|
-
peer_id: String,
|
|
51
|
-
messages: VecDeque<TrackedMessage>,
|
|
52
|
-
next_seq: Arc<AtomicU64>,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
impl PeerReplicationQueue {
|
|
56
|
-
pub fn new(peer_id: String) -> Self {
|
|
57
|
-
Self {
|
|
58
|
-
peer_id,
|
|
59
|
-
messages: VecDeque::new(),
|
|
60
|
-
next_seq: Arc::new(AtomicU64::new(1)),
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
pub fn enqueue(&mut self, message: ReplicationMessage) {
|
|
65
|
-
self.messages.push_back(TrackedMessage::new(message));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
pub fn pending_count(&self) -> usize {
|
|
69
|
-
self.messages
|
|
70
|
-
.iter()
|
|
71
|
-
.filter(|m| m.status == DeliveryStatus::Pending)
|
|
72
|
-
.count()
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
pub fn next_pending(&mut self) -> Option<TrackedMessage> {
|
|
76
|
-
for msg in &mut self.messages {
|
|
77
|
-
if msg.status == DeliveryStatus::Pending {
|
|
78
|
-
msg.send_count += 1;
|
|
79
|
-
return Some(msg.clone());
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
None
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
pub fn mark_delivered(&mut self, seq: u64) {
|
|
86
|
-
if seq > 0 && seq as usize <= self.messages.len() {
|
|
87
|
-
if let Some(msg) = self.messages.get_mut((seq - 1) as usize) {
|
|
88
|
-
msg.status = DeliveryStatus::Delivered;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/// Replication manager for a cluster
|
|
95
|
-
pub struct ReplicationManager {
|
|
96
|
-
peer_queues: HashMap<String, PeerReplicationQueue>,
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
impl ReplicationManager {
|
|
100
|
-
pub fn new() -> Self {
|
|
101
|
-
Self {
|
|
102
|
-
peer_queues: HashMap::new(),
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/// Register a peer to receive replication messages
|
|
107
|
-
pub fn register_peer(&mut self, peer_id: String) {
|
|
108
|
-
self.peer_queues
|
|
109
|
-
.insert(peer_id.clone(), PeerReplicationQueue::new(peer_id));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/// Enqueue a message for replication to all peers
|
|
113
|
-
pub fn replicate_to_all(&mut self, message: ReplicationMessage) {
|
|
114
|
-
for queue in self.peer_queues.values_mut() {
|
|
115
|
-
queue.enqueue(message.clone());
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/// Enqueue a message for replication to a specific peer
|
|
120
|
-
pub fn replicate_to_peer(&mut self, peer_id: &str, message: ReplicationMessage) {
|
|
121
|
-
if let Some(queue) = self.peer_queues.get_mut(peer_id) {
|
|
122
|
-
queue.enqueue(message);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/// Get pending messages for a peer
|
|
127
|
-
pub fn get_pending_for_peer(&mut self, peer_id: &str) -> Vec<TrackedMessage> {
|
|
128
|
-
let mut result = Vec::new();
|
|
129
|
-
if let Some(queue) = self.peer_queues.get_mut(peer_id) {
|
|
130
|
-
while let Some(msg) = queue.next_pending() {
|
|
131
|
-
result.push(msg);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
result
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/// Mark a message as delivered to a peer
|
|
138
|
-
pub fn mark_peer_delivered(&mut self, peer_id: &str, seq: u64) {
|
|
139
|
-
if let Some(queue) = self.peer_queues.get_mut(peer_id) {
|
|
140
|
-
queue.mark_delivered(seq);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/// Get replication statistics
|
|
145
|
-
pub fn get_pending_count(&self) -> usize {
|
|
146
|
-
self.peer_queues.values().map(|q| q.pending_count()).sum()
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
#[cfg(test)]
|
|
151
|
-
mod tests {
|
|
152
|
-
use super::*;
|
|
153
|
-
|
|
154
|
-
#[test]
|
|
155
|
-
fn replication_manager_basic() {
|
|
156
|
-
let mut mgr = ReplicationManager::new();
|
|
157
|
-
mgr.register_peer("peer1".to_string());
|
|
158
|
-
|
|
159
|
-
// Verify peer registered
|
|
160
|
-
assert_eq!(mgr.peer_queues.len(), 1);
|
|
161
|
-
assert_eq!(mgr.get_pending_count(), 0);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/// High-level replication protocol abstraction
|
|
2
|
-
///
|
|
3
|
-
/// Decouples ReplicationMessage handling from transport details.
|
|
4
|
-
/// Works with typed messages (ReplicationMessage) rather than raw bytes.
|
|
5
|
-
use crate::distributed_transactions::ReplicationMessage;
|
|
6
|
-
use std::sync::atomic::{AtomicU64, Ordering};
|
|
7
|
-
use std::sync::Arc;
|
|
8
|
-
|
|
9
|
-
/// Protocol-level transport abstraction that works with ReplicationMessage
|
|
10
|
-
#[async_trait::async_trait]
|
|
11
|
-
pub trait ProtocolTransport: Send + Sync {
|
|
12
|
-
/// Send a replication message to a peer
|
|
13
|
-
async fn send(&self, message: ReplicationMessage) -> Result<(), ProtocolError>;
|
|
14
|
-
|
|
15
|
-
/// Receive replication messages (non-blocking, returns empty if none available)
|
|
16
|
-
async fn receive(&self) -> Result<Vec<ReplicationMessage>, ProtocolError>;
|
|
17
|
-
|
|
18
|
-
/// Connect to a peer (for real network transports)
|
|
19
|
-
async fn connect(&mut self, peer_addr: &str) -> Result<(), ProtocolError>;
|
|
20
|
-
|
|
21
|
-
/// Disconnect from a peer (for real network transports)
|
|
22
|
-
async fn disconnect(&mut self) -> Result<(), ProtocolError>;
|
|
23
|
-
|
|
24
|
-
/// Check if connected to a peer
|
|
25
|
-
fn is_connected(&self) -> bool;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/// Protocol errors
|
|
29
|
-
#[derive(Clone, Debug)]
|
|
30
|
-
pub enum ProtocolError {
|
|
31
|
-
SerializationError(String),
|
|
32
|
-
TransportError(String),
|
|
33
|
-
ConnectionError(String),
|
|
34
|
-
Timeout,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
impl std::fmt::Display for ProtocolError {
|
|
38
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
39
|
-
match self {
|
|
40
|
-
Self::SerializationError(s) => write!(f, "serialization error: {}", s),
|
|
41
|
-
Self::TransportError(s) => write!(f, "transport error: {}", s),
|
|
42
|
-
Self::ConnectionError(s) => write!(f, "connection error: {}", s),
|
|
43
|
-
Self::Timeout => write!(f, "timeout"),
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
impl std::error::Error for ProtocolError {}
|
|
49
|
-
|
|
50
|
-
/// Metrics for monitoring replication protocol
|
|
51
|
-
#[derive(Clone, Debug, Default)]
|
|
52
|
-
pub struct ProtocolMetrics {
|
|
53
|
-
messages_sent: Arc<AtomicU64>,
|
|
54
|
-
messages_received: Arc<AtomicU64>,
|
|
55
|
-
bytes_sent: Arc<AtomicU64>,
|
|
56
|
-
bytes_received: Arc<AtomicU64>,
|
|
57
|
-
errors: Arc<AtomicU64>,
|
|
58
|
-
connection_state_changes: Arc<AtomicU64>,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
impl ProtocolMetrics {
|
|
62
|
-
pub fn new() -> Self {
|
|
63
|
-
Self::default()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
pub fn record_send(&self, bytes: usize) {
|
|
67
|
-
self.messages_sent.fetch_add(1, Ordering::Relaxed);
|
|
68
|
-
self.bytes_sent.fetch_add(bytes as u64, Ordering::Relaxed);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
pub fn record_receive(&self, bytes: usize) {
|
|
72
|
-
self.messages_received.fetch_add(1, Ordering::Relaxed);
|
|
73
|
-
self.bytes_received
|
|
74
|
-
.fetch_add(bytes as u64, Ordering::Relaxed);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
pub fn record_error(&self) {
|
|
78
|
-
self.errors.fetch_add(1, Ordering::Relaxed);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
pub fn record_connection_state_change(&self) {
|
|
82
|
-
self.connection_state_changes
|
|
83
|
-
.fetch_add(1, Ordering::Relaxed);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
pub fn get_messages_sent(&self) -> u64 {
|
|
87
|
-
self.messages_sent.load(Ordering::Relaxed)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
pub fn get_messages_received(&self) -> u64 {
|
|
91
|
-
self.messages_received.load(Ordering::Relaxed)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
pub fn get_bytes_sent(&self) -> u64 {
|
|
95
|
-
self.bytes_sent.load(Ordering::Relaxed)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
pub fn get_bytes_received(&self) -> u64 {
|
|
99
|
-
self.bytes_received.load(Ordering::Relaxed)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
pub fn get_errors(&self) -> u64 {
|
|
103
|
-
self.errors.load(Ordering::Relaxed)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
pub fn get_connection_state_changes(&self) -> u64 {
|
|
107
|
-
self.connection_state_changes.load(Ordering::Relaxed)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
#[cfg(test)]
|
|
112
|
-
mod tests {
|
|
113
|
-
use super::*;
|
|
114
|
-
|
|
115
|
-
#[test]
|
|
116
|
-
fn metrics_track_messages() {
|
|
117
|
-
let metrics = ProtocolMetrics::new();
|
|
118
|
-
metrics.record_send(1024);
|
|
119
|
-
metrics.record_send(2048);
|
|
120
|
-
|
|
121
|
-
assert_eq!(metrics.get_messages_sent(), 2);
|
|
122
|
-
assert_eq!(metrics.get_bytes_sent(), 3072);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
#[test]
|
|
126
|
-
fn metrics_track_errors() {
|
|
127
|
-
let metrics = ProtocolMetrics::new();
|
|
128
|
-
metrics.record_error();
|
|
129
|
-
metrics.record_error();
|
|
130
|
-
|
|
131
|
-
assert_eq!(metrics.get_errors(), 2);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
/// Distributed Capability Routing module
|
|
2
|
-
///
|
|
3
|
-
/// Handles routing capability execution requests to appropriate peers based on:
|
|
4
|
-
/// - Local vs remote capability availability
|
|
5
|
-
/// - Required state version compatibility
|
|
6
|
-
/// - Peer state acquisition capabilities
|
|
7
|
-
/// - Execution ownership semantics
|
|
8
|
-
use crate::{CapabilityExecutionResult, CapabilityRef, DistributedCapabilityAdvertisement};
|
|
9
|
-
use serde::{Deserialize, Serialize};
|
|
10
|
-
use std::collections::HashMap;
|
|
11
|
-
|
|
12
|
-
/// Route decision for capability execution
|
|
13
|
-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
14
|
-
pub enum RouteDecision {
|
|
15
|
-
/// Execute locally
|
|
16
|
-
Local,
|
|
17
|
-
/// Execute remotely at specific peer
|
|
18
|
-
Remote(String), // peer_id
|
|
19
|
-
/// No suitable provider found
|
|
20
|
-
Unavailable,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/// State version tracking for a peer
|
|
24
|
-
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
25
|
-
pub struct PeerStateVersion {
|
|
26
|
-
/// Peer ID
|
|
27
|
-
pub peer_id: String,
|
|
28
|
-
/// Namespace
|
|
29
|
-
pub namespace: String,
|
|
30
|
-
/// Current version at this peer
|
|
31
|
-
pub version: u64,
|
|
32
|
-
/// When the version was last updated
|
|
33
|
-
pub updated_ms: u128,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
impl PeerStateVersion {
|
|
37
|
-
pub fn new(peer_id: String, namespace: String, version: u64) -> Self {
|
|
38
|
-
Self {
|
|
39
|
-
peer_id,
|
|
40
|
-
namespace,
|
|
41
|
-
version,
|
|
42
|
-
updated_ms: crate::now_ms(),
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/// State-aware capability routing engine
|
|
48
|
-
pub struct CapabilityRouter {
|
|
49
|
-
/// Local capabilities
|
|
50
|
-
local_capabilities: HashMap<String, DistributedCapabilityAdvertisement>,
|
|
51
|
-
/// Remote capabilities by peer
|
|
52
|
-
remote_capabilities: HashMap<String, Vec<DistributedCapabilityAdvertisement>>,
|
|
53
|
-
/// Peer state versions
|
|
54
|
-
peer_state_versions: HashMap<String, PeerStateVersion>,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
impl CapabilityRouter {
|
|
58
|
-
pub fn new() -> Self {
|
|
59
|
-
Self {
|
|
60
|
-
local_capabilities: HashMap::new(),
|
|
61
|
-
remote_capabilities: HashMap::new(),
|
|
62
|
-
peer_state_versions: HashMap::new(),
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/// Register a local capability
|
|
67
|
-
pub fn register_local(&mut self, ad: DistributedCapabilityAdvertisement) {
|
|
68
|
-
self.local_capabilities
|
|
69
|
-
.insert(ad.capability_ref.canonical(), ad);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/// Register a remote capability
|
|
73
|
-
pub fn register_remote(&mut self, ad: DistributedCapabilityAdvertisement) {
|
|
74
|
-
let peer_id = ad.peer_id.clone();
|
|
75
|
-
self.remote_capabilities
|
|
76
|
-
.entry(peer_id)
|
|
77
|
-
.or_insert_with(Vec::new)
|
|
78
|
-
.push(ad);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/// Update peer state version
|
|
82
|
-
pub fn update_peer_state(&mut self, peer_id: String, namespace: String, version: u64) {
|
|
83
|
-
let key = format!("{}:{}", peer_id, namespace);
|
|
84
|
-
self.peer_state_versions
|
|
85
|
-
.insert(key, PeerStateVersion::new(peer_id, namespace, version));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/// Get the state version a peer has for a namespace
|
|
89
|
-
pub fn get_peer_state_version(&self, peer_id: &str, namespace: &str) -> u64 {
|
|
90
|
-
let key = format!("{}:{}", peer_id, namespace);
|
|
91
|
-
self.peer_state_versions
|
|
92
|
-
.get(&key)
|
|
93
|
-
.map(|v| v.version)
|
|
94
|
-
.unwrap_or(0)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/// Route a capability execution request
|
|
98
|
-
pub fn route(
|
|
99
|
-
&self,
|
|
100
|
-
cap_ref: &CapabilityRef,
|
|
101
|
-
required_state_version: u64,
|
|
102
|
-
local_peer_id: &str,
|
|
103
|
-
) -> RouteDecision {
|
|
104
|
-
let canonical = cap_ref.canonical();
|
|
105
|
-
|
|
106
|
-
// Check if capability is available locally
|
|
107
|
-
if self.local_capabilities.contains_key(&canonical) {
|
|
108
|
-
// Check if local state meets requirements
|
|
109
|
-
if self.check_state_compatibility(local_peer_id, cap_ref, required_state_version) {
|
|
110
|
-
return RouteDecision::Local;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Find remote providers with compatible state
|
|
115
|
-
let providers = self.find_compatible_providers(cap_ref, required_state_version);
|
|
116
|
-
|
|
117
|
-
if let Some(provider) = providers.first() {
|
|
118
|
-
RouteDecision::Remote(provider.peer_id.clone())
|
|
119
|
-
} else {
|
|
120
|
-
RouteDecision::Unavailable
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/// Check if a peer has compatible state version
|
|
125
|
-
fn check_state_compatibility(
|
|
126
|
-
&self,
|
|
127
|
-
peer_id: &str,
|
|
128
|
-
cap_ref: &CapabilityRef,
|
|
129
|
-
required_version: u64,
|
|
130
|
-
) -> bool {
|
|
131
|
-
let peer_version = self.get_peer_state_version(peer_id, &cap_ref.namespace);
|
|
132
|
-
peer_version >= required_version
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/// Find providers with compatible state versions
|
|
136
|
-
pub fn find_compatible_providers(
|
|
137
|
-
&self,
|
|
138
|
-
cap_ref: &CapabilityRef,
|
|
139
|
-
required_state_version: u64,
|
|
140
|
-
) -> Vec<&DistributedCapabilityAdvertisement> {
|
|
141
|
-
let mut compatible = Vec::new();
|
|
142
|
-
|
|
143
|
-
for (peer_id, capabilities) in &self.remote_capabilities {
|
|
144
|
-
for cap_ad in capabilities {
|
|
145
|
-
if cap_ad.capability_ref.canonical() == cap_ref.canonical() {
|
|
146
|
-
if self.check_state_compatibility(peer_id, cap_ref, required_state_version) {
|
|
147
|
-
compatible.push(cap_ad);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
compatible
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/// Check if capability requires state acquisition
|
|
157
|
-
pub fn requires_state_acquisition(
|
|
158
|
-
&self,
|
|
159
|
-
provider_peer: &str,
|
|
160
|
-
cap_ref: &CapabilityRef,
|
|
161
|
-
required_state_version: u64,
|
|
162
|
-
) -> bool {
|
|
163
|
-
let peer_version = self.get_peer_state_version(provider_peer, &cap_ref.namespace);
|
|
164
|
-
peer_version < required_state_version
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/// Plan state acquisition - list namespaces that need to be acquired
|
|
168
|
-
pub fn plan_state_acquisition(
|
|
169
|
-
&self,
|
|
170
|
-
provider_peer: &str,
|
|
171
|
-
cap_ref: &CapabilityRef,
|
|
172
|
-
required_state_version: u64,
|
|
173
|
-
) -> Vec<String> {
|
|
174
|
-
let peer_version = self.get_peer_state_version(provider_peer, &cap_ref.namespace);
|
|
175
|
-
if peer_version < required_state_version {
|
|
176
|
-
vec![cap_ref.namespace.clone()]
|
|
177
|
-
} else {
|
|
178
|
-
Vec::new()
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
impl Default for CapabilityRouter {
|
|
184
|
-
fn default() -> Self {
|
|
185
|
-
Self::new()
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/// Execution claim tracker for single-owner semantics
|
|
190
|
-
pub struct ExecutionClaimer {
|
|
191
|
-
/// Claims by execution ID
|
|
192
|
-
claims: HashMap<String, ExecutionClaim>,
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/// A claim on an execution
|
|
196
|
-
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
197
|
-
pub struct ExecutionClaim {
|
|
198
|
-
/// Execution ID
|
|
199
|
-
pub execution_id: String,
|
|
200
|
-
/// Peer that claimed it
|
|
201
|
-
pub claimant: String,
|
|
202
|
-
/// Timestamp of claim
|
|
203
|
-
pub claimed_ms: u128,
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
impl ExecutionClaim {
|
|
207
|
-
pub fn new(execution_id: String, claimant: String) -> Self {
|
|
208
|
-
Self {
|
|
209
|
-
execution_id,
|
|
210
|
-
claimant,
|
|
211
|
-
claimed_ms: crate::now_ms(),
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
impl ExecutionClaimer {
|
|
217
|
-
pub fn new() -> Self {
|
|
218
|
-
Self {
|
|
219
|
-
claims: HashMap::new(),
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/// Attempt to claim an execution
|
|
224
|
-
/// Returns the claim if successful, None if already claimed
|
|
225
|
-
pub fn try_claim(&mut self, execution_id: String, claimant: String) -> Option<ExecutionClaim> {
|
|
226
|
-
if self.claims.contains_key(&execution_id) {
|
|
227
|
-
None
|
|
228
|
-
} else {
|
|
229
|
-
let claim = ExecutionClaim::new(execution_id.clone(), claimant);
|
|
230
|
-
self.claims.insert(execution_id, claim.clone());
|
|
231
|
-
Some(claim)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/// Get the claimant of an execution
|
|
236
|
-
pub fn get_claimant(&self, execution_id: &str) -> Option<&str> {
|
|
237
|
-
self.claims.get(execution_id).map(|c| c.claimant.as_str())
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/// Check if execution is claimed by a specific peer
|
|
241
|
-
pub fn is_claimed_by(&self, execution_id: &str, claimant: &str) -> bool {
|
|
242
|
-
self.claims
|
|
243
|
-
.get(execution_id)
|
|
244
|
-
.map(|c| c.claimant == claimant)
|
|
245
|
-
.unwrap_or(false)
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
impl Default for ExecutionClaimer {
|
|
250
|
-
fn default() -> Self {
|
|
251
|
-
Self::new()
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/// Result publication tracker
|
|
256
|
-
pub struct ExecutionResultPublisher {
|
|
257
|
-
/// Published results by execution ID
|
|
258
|
-
results: HashMap<String, CapabilityExecutionResult>,
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
impl ExecutionResultPublisher {
|
|
262
|
-
pub fn new() -> Self {
|
|
263
|
-
Self {
|
|
264
|
-
results: HashMap::new(),
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/// Publish an execution result
|
|
269
|
-
pub fn publish(&mut self, result: CapabilityExecutionResult) {
|
|
270
|
-
self.results
|
|
271
|
-
.insert(result.execution_ref.execution_id.clone(), result);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/// Get a published result
|
|
275
|
-
pub fn get_result(&self, execution_id: &str) -> Option<&CapabilityExecutionResult> {
|
|
276
|
-
self.results.get(execution_id)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/// Check if result exists
|
|
280
|
-
pub fn has_result(&self, execution_id: &str) -> bool {
|
|
281
|
-
self.results.contains_key(execution_id)
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
impl Default for ExecutionResultPublisher {
|
|
286
|
-
fn default() -> Self {
|
|
287
|
-
Self::new()
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
#[cfg(test)]
|
|
292
|
-
mod tests {
|
|
293
|
-
use super::*;
|
|
294
|
-
use crate::ExecutionRef;
|
|
295
|
-
|
|
296
|
-
fn make_cap_ref(namespace: &str, capability: &str, version: u32) -> CapabilityRef {
|
|
297
|
-
CapabilityRef::new(namespace.to_string(), capability.to_string(), version)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
fn make_capability_ad(
|
|
301
|
-
namespace: &str,
|
|
302
|
-
capability: &str,
|
|
303
|
-
version: u32,
|
|
304
|
-
peer_id: &str,
|
|
305
|
-
) -> DistributedCapabilityAdvertisement {
|
|
306
|
-
DistributedCapabilityAdvertisement::new(
|
|
307
|
-
make_cap_ref(namespace, capability, version),
|
|
308
|
-
peer_id.to_string(),
|
|
309
|
-
)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
#[test]
|
|
313
|
-
fn test_router_local_capability() {
|
|
314
|
-
let mut router = CapabilityRouter::new();
|
|
315
|
-
let ad = make_capability_ad("docs", "vector-search", 1, "local");
|
|
316
|
-
router.register_local(ad);
|
|
317
|
-
|
|
318
|
-
router.update_peer_state("local".to_string(), "docs".to_string(), 851);
|
|
319
|
-
|
|
320
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
321
|
-
let decision = router.route(&cap_ref, 851, "local");
|
|
322
|
-
assert_eq!(decision, RouteDecision::Local);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
#[test]
|
|
326
|
-
fn test_router_remote_capability() {
|
|
327
|
-
let mut router = CapabilityRouter::new();
|
|
328
|
-
let ad = make_capability_ad("docs", "vector-search", 1, "peer-b");
|
|
329
|
-
router.register_remote(ad);
|
|
330
|
-
|
|
331
|
-
router.update_peer_state("peer-b".to_string(), "docs".to_string(), 851);
|
|
332
|
-
|
|
333
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
334
|
-
let decision = router.route(&cap_ref, 851, "peer-a");
|
|
335
|
-
assert_eq!(decision, RouteDecision::Remote("peer-b".to_string()));
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
#[test]
|
|
339
|
-
fn test_router_unavailable() {
|
|
340
|
-
let router = CapabilityRouter::new();
|
|
341
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
342
|
-
let decision = router.route(&cap_ref, 851, "peer-a");
|
|
343
|
-
assert_eq!(decision, RouteDecision::Unavailable);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
#[test]
|
|
347
|
-
fn test_router_state_mismatch() {
|
|
348
|
-
let mut router = CapabilityRouter::new();
|
|
349
|
-
let ad = make_capability_ad("docs", "vector-search", 1, "peer-b");
|
|
350
|
-
router.register_remote(ad);
|
|
351
|
-
|
|
352
|
-
// Peer only has version 800, but we need 851
|
|
353
|
-
router.update_peer_state("peer-b".to_string(), "docs".to_string(), 800);
|
|
354
|
-
|
|
355
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
356
|
-
let decision = router.route(&cap_ref, 851, "peer-a");
|
|
357
|
-
assert_eq!(decision, RouteDecision::Unavailable);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
#[test]
|
|
361
|
-
fn test_router_requires_state_acquisition() {
|
|
362
|
-
let mut router = CapabilityRouter::new();
|
|
363
|
-
router.update_peer_state("peer-b".to_string(), "docs".to_string(), 800);
|
|
364
|
-
|
|
365
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
366
|
-
assert!(router.requires_state_acquisition("peer-b", &cap_ref, 851));
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
#[test]
|
|
370
|
-
fn test_execution_claimer_single_claim() {
|
|
371
|
-
let mut claimer = ExecutionClaimer::new();
|
|
372
|
-
let claim = claimer.try_claim("exec-123".to_string(), "peer-a".to_string());
|
|
373
|
-
assert!(claim.is_some());
|
|
374
|
-
assert_eq!(claim.unwrap().claimant, "peer-a");
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
#[test]
|
|
378
|
-
fn test_execution_claimer_duplicate_claim() {
|
|
379
|
-
let mut claimer = ExecutionClaimer::new();
|
|
380
|
-
let claim1 = claimer.try_claim("exec-123".to_string(), "peer-a".to_string());
|
|
381
|
-
let claim2 = claimer.try_claim("exec-123".to_string(), "peer-b".to_string());
|
|
382
|
-
|
|
383
|
-
assert!(claim1.is_some());
|
|
384
|
-
assert!(claim2.is_none());
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
#[test]
|
|
388
|
-
fn test_execution_claimer_get_claimant() {
|
|
389
|
-
let mut claimer = ExecutionClaimer::new();
|
|
390
|
-
claimer.try_claim("exec-123".to_string(), "peer-a".to_string());
|
|
391
|
-
|
|
392
|
-
let claimant = claimer.get_claimant("exec-123");
|
|
393
|
-
assert_eq!(claimant, Some("peer-a"));
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
#[test]
|
|
397
|
-
fn test_execution_result_publisher() {
|
|
398
|
-
let mut publisher = ExecutionResultPublisher::new();
|
|
399
|
-
let cap_ref = make_cap_ref("docs", "vector-search", 1);
|
|
400
|
-
let exec_ref = ExecutionRef::new("exec-123".to_string(), cap_ref, "peer-b".to_string());
|
|
401
|
-
let result = serde_json::json!({"results": [1, 2, 3]});
|
|
402
|
-
let exec_result = CapabilityExecutionResult::success(exec_ref, result);
|
|
403
|
-
|
|
404
|
-
publisher.publish(exec_result);
|
|
405
|
-
|
|
406
|
-
assert!(publisher.has_result("exec-123"));
|
|
407
|
-
assert!(publisher.get_result("exec-123").is_some());
|
|
408
|
-
}
|
|
409
|
-
}
|