@feltdb/core 0.8.4 → 0.8.6
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/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/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 +1648 -46
- 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.rs +39 -0
- 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 +79 -70
- 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_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 +13 -4
- 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 +1565 -536
- 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/storage.rs +9 -3
- package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
- 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 +3 -4
- package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +132 -0
- package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
- package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +272 -0
- package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +467 -0
- package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +309 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +445 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +518 -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/operational_health_contract.rs +278 -0
- package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +2 -1
- package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +80 -25
- 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 +1365 -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/replicated_history_contract.rs +417 -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/tests/workload_envelope_contract.rs +442 -0
- package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +16 -1
- package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +695 -47
- package/dist/create/server-source/crates/feltdb-server/src/metrics.rs +21 -0
- package/dist/studio-app/assets/{feltdb_wasm-CVQWgXO-.js → feltdb_wasm-C1VhI-U5.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-C8HXbAXb.wasm +0 -0
- package/dist/studio-app/assets/{index-DwgNAIIX.js → index-Bbos1m2U.js} +1 -1
- package/dist/studio-app/index.html +1 -1
- 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-CNVpvaZV.wasm +0 -0
|
@@ -157,13 +157,19 @@ impl Storage for FileStorage {
|
|
|
157
157
|
let file = OpenOptions::new().read(true).open(&self.path)?;
|
|
158
158
|
let reader = BufReader::new(file);
|
|
159
159
|
|
|
160
|
-
for line in reader.lines() {
|
|
160
|
+
for (index, line) in reader.lines().enumerate() {
|
|
161
161
|
let line = line?;
|
|
162
162
|
if line.trim().is_empty() {
|
|
163
163
|
continue;
|
|
164
164
|
}
|
|
165
|
-
let row: StoredRow = serde_json::from_str(&line)
|
|
166
|
-
|
|
165
|
+
let row: StoredRow = serde_json::from_str(&line).map_err(|_| {
|
|
166
|
+
FlowError::CorruptLogLine(Box::new(crate::LogCorruption {
|
|
167
|
+
line_number: index + 1,
|
|
168
|
+
byte_offset: 0,
|
|
169
|
+
reason: "not a durable record this build understands".to_string(),
|
|
170
|
+
excerpt: line.chars().take(120).collect(),
|
|
171
|
+
}))
|
|
172
|
+
})?;
|
|
167
173
|
operations.push(row);
|
|
168
174
|
}
|
|
169
175
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
///
|
|
3
3
|
/// Integrates the admission contract with actual operation submission,
|
|
4
4
|
/// ensuring no silent failures and explicit rejection semantics.
|
|
5
|
-
|
|
6
5
|
use crate::admission::{ProductionRetryPolicy, RejectionReason, SubmissionOutcome};
|
|
7
6
|
use crate::transaction_api::{TransactionManager, TxError};
|
|
8
7
|
use crate::transactions::{ConsistencyContract, Operation};
|
|
@@ -243,11 +242,8 @@ impl SubmissionManager {
|
|
|
243
242
|
let mut manager = self.transaction_manager.lock().unwrap();
|
|
244
243
|
|
|
245
244
|
// Extract operation ID - this is the unique identifier
|
|
246
|
-
let operation_id =
|
|
247
|
-
&operation.operation_id.sequence.to_string(),
|
|
248
|
-
10,
|
|
249
|
-
)
|
|
250
|
-
.unwrap_or(0);
|
|
245
|
+
let operation_id =
|
|
246
|
+
u64::from_str_radix(&operation.operation_id.sequence.to_string(), 10).unwrap_or(0);
|
|
251
247
|
|
|
252
248
|
// Attempt to execute transaction
|
|
253
249
|
match manager.execute_and_commit(
|
|
@@ -259,11 +255,9 @@ impl SubmissionManager {
|
|
|
259
255
|
Err(err) => {
|
|
260
256
|
// Map TxError to RejectionReason
|
|
261
257
|
match err {
|
|
262
|
-
TxError::OperationDeduplication(_) => {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
})
|
|
266
|
-
}
|
|
258
|
+
TxError::OperationDeduplication(_) => Err(RejectionReason::DuplicateDetected {
|
|
259
|
+
original_operation_id: operation_id,
|
|
260
|
+
}),
|
|
267
261
|
TxError::PreconditionFailed(_) | TxError::ConflictDetected(_) => {
|
|
268
262
|
// These could indicate lock contention
|
|
269
263
|
Err(RejectionReason::TransientLockContention)
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
/// - Bounded buffers (prevent unbounded growth)
|
|
18
18
|
///
|
|
19
19
|
/// Deduplication/idempotency/retry logic is the protocol's responsibility via DistributedTransactionExecutor.
|
|
20
|
-
|
|
21
20
|
use crate::distributed_transactions::ReplicationMessage;
|
|
22
21
|
use crate::replica_acknowledgements::ReplicaAcknowledgement;
|
|
23
22
|
|
|
@@ -286,10 +285,7 @@ mod tests {
|
|
|
286
285
|
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
|
287
286
|
|
|
288
287
|
// Client connects
|
|
289
|
-
client
|
|
290
|
-
.connect(server_addr)
|
|
291
|
-
.await
|
|
292
|
-
.expect("client connect");
|
|
288
|
+
client.connect(server_addr).await.expect("client connect");
|
|
293
289
|
|
|
294
290
|
// Wait for server to process connection
|
|
295
291
|
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
|
@@ -376,7 +372,8 @@ mod tests {
|
|
|
376
372
|
);
|
|
377
373
|
|
|
378
374
|
let serialized = serde_json::to_vec(&msg).expect("serialize");
|
|
379
|
-
let deserialized: ReplicationMessage =
|
|
375
|
+
let deserialized: ReplicationMessage =
|
|
376
|
+
serde_json::from_slice(&serialized).expect("deserialize");
|
|
380
377
|
|
|
381
378
|
assert_eq!(msg.from_node, deserialized.from_node);
|
|
382
379
|
assert_eq!(msg.to_node, deserialized.to_node);
|
|
@@ -387,8 +384,8 @@ mod tests {
|
|
|
387
384
|
fn bincode_serialization_with_operation() {
|
|
388
385
|
use crate::convergence::VectorClock;
|
|
389
386
|
use crate::transactions::{Operation, OperationCommand, OperationId, StateVersion};
|
|
390
|
-
use std::collections::HashMap;
|
|
391
387
|
use serde_json::json;
|
|
388
|
+
use std::collections::HashMap;
|
|
392
389
|
|
|
393
390
|
let mut fields = HashMap::new();
|
|
394
391
|
fields.insert("key1".to_string(), json!("value1"));
|
|
@@ -426,7 +423,8 @@ mod tests {
|
|
|
426
423
|
let serialized = serde_json::to_vec(&msg).expect("serialize");
|
|
427
424
|
println!("Serialized {} bytes", serialized.len());
|
|
428
425
|
|
|
429
|
-
let deserialized: ReplicationMessage =
|
|
426
|
+
let deserialized: ReplicationMessage =
|
|
427
|
+
serde_json::from_slice(&serialized).expect("deserialize");
|
|
430
428
|
|
|
431
429
|
assert_eq!(msg.from_node, deserialized.from_node);
|
|
432
430
|
assert_eq!(msg.to_node, deserialized.to_node);
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
/// - StateTransitionStore for transition durability
|
|
7
7
|
/// - Precondition validation
|
|
8
8
|
/// - Read/write dependency tracking
|
|
9
|
-
|
|
10
9
|
use crate::convergence::VectorClock;
|
|
11
10
|
use crate::operation_log::{MemoryOperationLog, OperationLogEntry};
|
|
12
11
|
use crate::state_transition_store::{MemoryStateTransitionStore, StateTransitionRecord};
|
|
@@ -31,7 +30,9 @@ impl std::fmt::Display for TxError {
|
|
|
31
30
|
match self {
|
|
32
31
|
TxError::PreconditionFailed(msg) => write!(f, "Precondition failed: {}", msg),
|
|
33
32
|
TxError::ConflictDetected(msg) => write!(f, "Conflict detected: {}", msg),
|
|
34
|
-
TxError::OperationDeduplication(msg) =>
|
|
33
|
+
TxError::OperationDeduplication(msg) => {
|
|
34
|
+
write!(f, "Operation already executed: {}", msg)
|
|
35
|
+
}
|
|
35
36
|
TxError::InvalidState(msg) => write!(f, "Invalid state: {}", msg),
|
|
36
37
|
TxError::PersistenceFailure(msg) => write!(f, "Persistence failure: {}", msg),
|
|
37
38
|
}
|
|
@@ -99,7 +100,9 @@ impl TransactionManager {
|
|
|
99
100
|
|
|
100
101
|
// 4. Validate transition succeeded
|
|
101
102
|
if !transition.is_successful() {
|
|
102
|
-
return Err(TxError::InvalidState(
|
|
103
|
+
return Err(TxError::InvalidState(
|
|
104
|
+
"Transaction execution failed".to_string(),
|
|
105
|
+
));
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
// 5. Persist operations to operation log
|
|
@@ -110,7 +113,8 @@ impl TransactionManager {
|
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
// 6. Persist transition to state transition store
|
|
113
|
-
let store_index = self
|
|
116
|
+
let store_index = self
|
|
117
|
+
.transition_store
|
|
114
118
|
.record_transition(transition.clone())
|
|
115
119
|
.map_err(|e| TxError::PersistenceFailure(e))?;
|
|
116
120
|
|
|
@@ -121,9 +125,12 @@ impl TransactionManager {
|
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
// 8. Retrieve the recorded transition
|
|
124
|
-
let record = self
|
|
128
|
+
let record = self
|
|
129
|
+
.transition_store
|
|
125
130
|
.get_by_index(store_index)
|
|
126
|
-
.ok_or_else(||
|
|
131
|
+
.ok_or_else(|| {
|
|
132
|
+
TxError::PersistenceFailure("Failed to retrieve recorded transition".to_string())
|
|
133
|
+
})?;
|
|
127
134
|
|
|
128
135
|
Ok(record)
|
|
129
136
|
}
|
|
@@ -191,10 +198,7 @@ impl TransactionManager {
|
|
|
191
198
|
|
|
192
199
|
/// Validate preconditions for an operation
|
|
193
200
|
/// (Simple string matching - production would have actual condition evaluation)
|
|
194
|
-
pub fn validate_preconditions(
|
|
195
|
-
&self,
|
|
196
|
-
operation: &Operation,
|
|
197
|
-
) -> TxResult<()> {
|
|
201
|
+
pub fn validate_preconditions(&self, operation: &Operation) -> TxResult<()> {
|
|
198
202
|
if operation.preconditions.is_empty() {
|
|
199
203
|
return Ok(());
|
|
200
204
|
}
|
|
@@ -257,11 +261,8 @@ mod tests {
|
|
|
257
261
|
"user".to_string(),
|
|
258
262
|
);
|
|
259
263
|
|
|
260
|
-
let result =
|
|
261
|
-
"txn1".to_string(),
|
|
262
|
-
vec![op],
|
|
263
|
-
ConsistencyContract::local(),
|
|
264
|
-
);
|
|
264
|
+
let result =
|
|
265
|
+
manager.execute_and_commit("txn1".to_string(), vec![op], ConsistencyContract::local());
|
|
265
266
|
|
|
266
267
|
assert!(result.is_ok());
|
|
267
268
|
assert_eq!(manager.operation_log_size(), 1);
|
|
@@ -299,11 +300,8 @@ mod tests {
|
|
|
299
300
|
ConsistencyContract::local(),
|
|
300
301
|
);
|
|
301
302
|
|
|
302
|
-
let result =
|
|
303
|
-
"txn2".to_string(),
|
|
304
|
-
vec![op],
|
|
305
|
-
ConsistencyContract::local(),
|
|
306
|
-
);
|
|
303
|
+
let result =
|
|
304
|
+
manager.execute_and_commit("txn2".to_string(), vec![op], ConsistencyContract::local());
|
|
307
305
|
|
|
308
306
|
assert!(result.is_err());
|
|
309
307
|
assert!(result.unwrap_err().to_string().contains("already executed"));
|
|
@@ -335,11 +333,8 @@ mod tests {
|
|
|
335
333
|
"user".to_string(),
|
|
336
334
|
);
|
|
337
335
|
|
|
338
|
-
let _ =
|
|
339
|
-
"txn1".to_string(),
|
|
340
|
-
vec![op],
|
|
341
|
-
ConsistencyContract::local(),
|
|
342
|
-
);
|
|
336
|
+
let _ =
|
|
337
|
+
manager.execute_and_commit("txn1".to_string(), vec![op], ConsistencyContract::local());
|
|
343
338
|
|
|
344
339
|
let retrieved = manager.get_operation(&op_id);
|
|
345
340
|
assert!(retrieved.is_some());
|
|
@@ -370,11 +365,8 @@ mod tests {
|
|
|
370
365
|
"user".to_string(),
|
|
371
366
|
);
|
|
372
367
|
|
|
373
|
-
let _ =
|
|
374
|
-
"txn1".to_string(),
|
|
375
|
-
vec![op],
|
|
376
|
-
ConsistencyContract::local(),
|
|
377
|
-
);
|
|
368
|
+
let _ =
|
|
369
|
+
manager.execute_and_commit("txn1".to_string(), vec![op], ConsistencyContract::local());
|
|
378
370
|
|
|
379
371
|
let transition = manager.get_transition("txn1");
|
|
380
372
|
assert!(transition.is_some());
|
|
@@ -461,11 +453,8 @@ mod tests {
|
|
|
461
453
|
"user".to_string(),
|
|
462
454
|
);
|
|
463
455
|
|
|
464
|
-
let _ =
|
|
465
|
-
"txn1".to_string(),
|
|
466
|
-
vec![op],
|
|
467
|
-
ConsistencyContract::local(),
|
|
468
|
-
);
|
|
456
|
+
let _ =
|
|
457
|
+
manager.execute_and_commit("txn1".to_string(), vec![op], ConsistencyContract::local());
|
|
469
458
|
|
|
470
459
|
let new_version = manager.current_state_version();
|
|
471
460
|
assert_ne!(new_version.state_hash, initial_hash);
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
/// 6. Consistency Contracts: Per-transaction guarantees
|
|
11
11
|
/// 7. Derived State: Rebuildable from operation log
|
|
12
12
|
/// 8. Partition Tolerance: Divergence + deterministic reconciliation
|
|
13
|
-
|
|
14
13
|
use crate::convergence::VectorClock;
|
|
15
14
|
use crate::transactions::*;
|
|
16
15
|
use std::collections::HashMap;
|
|
@@ -235,7 +234,10 @@ mod invariant_tests {
|
|
|
235
234
|
assert!(tx2.is_successful());
|
|
236
235
|
|
|
237
236
|
let conflicts = CommitValidator::detect_conflicts(&tx1, &[tx2]);
|
|
238
|
-
assert!(
|
|
237
|
+
assert!(
|
|
238
|
+
conflicts.is_empty(),
|
|
239
|
+
"Non-overlapping writes should not conflict"
|
|
240
|
+
);
|
|
239
241
|
}
|
|
240
242
|
|
|
241
243
|
#[test]
|
|
@@ -322,7 +324,10 @@ mod invariant_tests {
|
|
|
322
324
|
assert!(tx2.is_successful());
|
|
323
325
|
|
|
324
326
|
let conflicts = CommitValidator::detect_conflicts(&tx1, &[tx2]);
|
|
325
|
-
assert!(
|
|
327
|
+
assert!(
|
|
328
|
+
!conflicts.is_empty(),
|
|
329
|
+
"Write-write conflicts should be detected"
|
|
330
|
+
);
|
|
326
331
|
assert!(
|
|
327
332
|
conflicts.iter().any(|c| c.contains("Write-write")),
|
|
328
333
|
"Should specifically identify write-write conflict"
|
|
@@ -446,7 +451,8 @@ mod invariant_tests {
|
|
|
446
451
|
assert!(tx1.is_successful(), "Tx1 should succeed");
|
|
447
452
|
assert!(tx2.is_successful(), "Tx2 should succeed");
|
|
448
453
|
assert_eq!(
|
|
449
|
-
tx1.operations.len(),
|
|
454
|
+
tx1.operations.len(),
|
|
455
|
+
tx2.operations.len(),
|
|
450
456
|
"Both transactions should have same number of operations"
|
|
451
457
|
);
|
|
452
458
|
}
|
|
@@ -493,7 +499,10 @@ mod invariant_tests {
|
|
|
493
499
|
ConsistencyContract::eventual(),
|
|
494
500
|
);
|
|
495
501
|
|
|
496
|
-
assert!(
|
|
502
|
+
assert!(
|
|
503
|
+
!tx.is_successful(),
|
|
504
|
+
"Duplicate operation should be rejected"
|
|
505
|
+
);
|
|
497
506
|
}
|
|
498
507
|
|
|
499
508
|
#[test]
|
|
@@ -623,8 +632,12 @@ mod invariant_tests {
|
|
|
623
632
|
to_vc.increment("node1");
|
|
624
633
|
let to_version = StateVersion::new(to_vc, "hash1".to_string());
|
|
625
634
|
|
|
626
|
-
let transition =
|
|
627
|
-
|
|
635
|
+
let transition = executor.execute_transaction(
|
|
636
|
+
"tx1".to_string(),
|
|
637
|
+
version,
|
|
638
|
+
ops.clone(),
|
|
639
|
+
ConsistencyContract::local(),
|
|
640
|
+
);
|
|
628
641
|
|
|
629
642
|
assert_eq!(transition.operations.len(), ops.len());
|
|
630
643
|
|
|
@@ -944,6 +957,9 @@ mod invariant_tests {
|
|
|
944
957
|
);
|
|
945
958
|
|
|
946
959
|
let conflicts = CommitValidator::detect_conflicts(&tx1, &[tx2]);
|
|
947
|
-
assert!(
|
|
960
|
+
assert!(
|
|
961
|
+
!conflicts.is_empty(),
|
|
962
|
+
"Write-skew scenario should detect potential conflict"
|
|
963
|
+
);
|
|
948
964
|
}
|
|
949
965
|
}
|