create-feltdb 0.9.1 → 0.10.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/package-versions.js +1 -1
- package/dist/server-source/crates/feltdb/src/acceptance_tests.rs +8 -1
- package/dist/server-source/crates/feltdb/src/application.rs +16 -0
- package/dist/server-source/crates/feltdb/src/bin/feltdb_node.rs +21 -22
- package/dist/server-source/crates/feltdb/src/lib.rs +451 -33
- package/dist/server-source/crates/feltdb/src/state_contract.rs +48 -3
- package/dist/server-source/crates/feltdb/src/state_model.rs +569 -4
- package/dist/server-source/crates/feltdb/src/state_trigger.rs +1 -0
- package/dist/server-source/crates/feltdb/src/versioned_object_substrate.rs +708 -0
- package/dist/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
- package/dist/server-source/crates/feltdb/src/workload.rs +480 -44
- package/dist/server-source/crates/feltdb/tests/generalized_version_control_evidence.rs +123 -0
- package/dist/server-source/crates/feltdb/tests/generalized_version_control_substrate_completion.rs +281 -0
- package/dist/server-source/crates/feltdb/tests/production_readiness_contract.rs +15 -3
- package/dist/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +28 -18
- package/dist/server-source/crates/feltdb/tests/storage_independent_versioned_object_substrate.rs +328 -0
- package/dist/server-source/crates/feltdb/tests/workload_envelope_contract.rs +20 -3
- package/dist/server-source/crates/feltdb-server/src/app_state.rs +14 -4
- package/dist/server-source/crates/feltdb-server/src/backup.rs +0 -4
- package/dist/server-source/crates/feltdb-server/src/canonical_principals.rs +1093 -0
- package/dist/server-source/crates/feltdb-server/src/causal.rs +905 -144
- package/dist/server-source/crates/feltdb-server/src/connections.rs +9 -6
- package/dist/server-source/crates/feltdb-server/src/control_plane.rs +90 -0
- package/dist/server-source/crates/feltdb-server/src/lib.rs +1 -0
- package/dist/server-source/crates/feltdb-server/src/main.rs +408 -74
- package/dist/server-source/crates/feltdb-server/src/principals.rs +9 -501
- package/dist/server-source/crates/feltdb-server/src/tenancy.rs +22 -0
- package/dist/server-source/crates/feltdb-server/tests/principal_tenant_migration.rs +247 -0
- package/package.json +1 -1
package/dist/package-versions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// One release train keeps generated applications installable. The repository
|
|
2
2
|
// validation script checks these values against every workspace manifest.
|
|
3
|
-
export const FELTDB_PACKAGE_VERSION = '0.
|
|
3
|
+
export const FELTDB_PACKAGE_VERSION = '0.10.0';
|
|
4
4
|
export const feltdbPackageRange = `^${FELTDB_PACKAGE_VERSION}`;
|
|
@@ -1460,9 +1460,12 @@ mod convergence_acceptance_tests {
|
|
|
1460
1460
|
use crate::FeltDb;
|
|
1461
1461
|
use serde::{Deserialize, Serialize};
|
|
1462
1462
|
use std::path::PathBuf;
|
|
1463
|
+
use std::sync::atomic::{AtomicU64, Ordering};
|
|
1463
1464
|
use std::time::SystemTime;
|
|
1464
1465
|
use std::time::UNIX_EPOCH;
|
|
1465
1466
|
|
|
1467
|
+
static TEMP_FILE_SEQUENCE: AtomicU64 = AtomicU64::new(0);
|
|
1468
|
+
|
|
1466
1469
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
1467
1470
|
struct Task {
|
|
1468
1471
|
title: String,
|
|
@@ -1475,7 +1478,11 @@ mod convergence_acceptance_tests {
|
|
|
1475
1478
|
.duration_since(UNIX_EPOCH)
|
|
1476
1479
|
.expect("time")
|
|
1477
1480
|
.as_nanos();
|
|
1478
|
-
|
|
1481
|
+
let sequence = TEMP_FILE_SEQUENCE.fetch_add(1, Ordering::Relaxed);
|
|
1482
|
+
std::env::temp_dir().join(format!(
|
|
1483
|
+
"feltdb-convergence-test-{}-{nanos}-{sequence}.data",
|
|
1484
|
+
std::process::id()
|
|
1485
|
+
))
|
|
1479
1486
|
}
|
|
1480
1487
|
|
|
1481
1488
|
/// Test convergence: Two instances make concurrent mutations on same key
|
|
@@ -1203,6 +1203,22 @@ impl ApplicationStore {
|
|
|
1203
1203
|
records: Arc::new(RwLock::new(records)),
|
|
1204
1204
|
})
|
|
1205
1205
|
}
|
|
1206
|
+
|
|
1207
|
+
/// Return every tenant scope asserted by canonical application definition
|
|
1208
|
+
/// records for one stable application identity. Callers must reject zero
|
|
1209
|
+
/// or multiple distinct tenants; ordering is never ownership evidence.
|
|
1210
|
+
pub fn tenant_ownership_candidates(&self, application_id: &str) -> Vec<String> {
|
|
1211
|
+
let Ok(records) = self.records.read() else {
|
|
1212
|
+
return Vec::new();
|
|
1213
|
+
};
|
|
1214
|
+
records
|
|
1215
|
+
.revisions
|
|
1216
|
+
.iter()
|
|
1217
|
+
.map(|value| (&value.application_id, &value.tenant_id))
|
|
1218
|
+
.filter(|(candidate, _)| candidate.as_str() == application_id)
|
|
1219
|
+
.map(|(_, tenant)| tenant.clone())
|
|
1220
|
+
.collect()
|
|
1221
|
+
}
|
|
1206
1222
|
fn persist(&self, r: &RevisionRecords) -> Result<(), String> {
|
|
1207
1223
|
if let Some(parent) = self.path.parent() {
|
|
1208
1224
|
fs::create_dir_all(parent).map_err(|e| e.to_string())?;
|
|
@@ -744,11 +744,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
744
744
|
link.peer.clone(),
|
|
745
745
|
envelope.envelope_id.sequence,
|
|
746
746
|
);
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
747
|
+
// Forwarding, like re-sending, is an explicit
|
|
748
|
+
// recovery operation. Prefer a fresh connection so
|
|
749
|
+
// a peer restart cannot leave this write accepted
|
|
750
|
+
// by a stale local socket and delivered nowhere.
|
|
751
|
+
let _ = connect_with_retry(link, 3).await;
|
|
752
|
+
if link.io.send(message).await.is_ok() {
|
|
752
753
|
delivered.push(link.peer.clone());
|
|
753
754
|
}
|
|
754
755
|
}
|
|
@@ -793,19 +794,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
793
794
|
link.peer.clone(),
|
|
794
795
|
envelope.envelope_id.sequence,
|
|
795
796
|
);
|
|
796
|
-
//
|
|
797
|
-
//
|
|
798
|
-
//
|
|
799
|
-
//
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
delivered.push(link.peer.clone());
|
|
807
|
-
}
|
|
808
|
-
}
|
|
797
|
+
// Re-sending is the recovery primitive used after a
|
|
798
|
+
// peer restart. A write to the old TCP socket can
|
|
799
|
+
// still return success after the peer has exited,
|
|
800
|
+
// because that only confirms acceptance by the
|
|
801
|
+
// local kernel. Try to establish a fresh connection
|
|
802
|
+
// first. If the peer never restarted, the connect
|
|
803
|
+
// attempt leaves the established stream untouched.
|
|
804
|
+
let _ = connect_with_retry(link, 3).await;
|
|
805
|
+
if link.io.send(message).await.is_ok() {
|
|
806
|
+
delivered.push(link.peer.clone());
|
|
809
807
|
}
|
|
810
808
|
}
|
|
811
809
|
println!(
|
|
@@ -961,12 +959,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
961
959
|
|
|
962
960
|
let mut delivered = Vec::new();
|
|
963
961
|
for link in &send_links {
|
|
962
|
+
// Acknowledgements are durable recovery evidence and are
|
|
963
|
+
// commonly rebroadcast after a peer restart. Refresh the
|
|
964
|
+
// connection first for the same reason as explicit
|
|
965
|
+
// envelope replay.
|
|
966
|
+
let _ = connect_with_retry(link, 3).await;
|
|
964
967
|
if link.io.send_acknowledgement(ack.clone()).await.is_ok() {
|
|
965
968
|
delivered.push(link.peer.clone());
|
|
966
|
-
} else if connect_with_retry(link, 3).await
|
|
967
|
-
&& link.io.send_acknowledgement(ack.clone()).await.is_ok()
|
|
968
|
-
{
|
|
969
|
-
delivered.push(link.peer.clone());
|
|
970
969
|
}
|
|
971
970
|
}
|
|
972
971
|
println!(
|