offline_protocol_reliability/
constants.rs1pub const DEFAULT_ACK_TIMEOUT_MS: u64 = 10000;
5
6pub const DEFAULT_MAX_PENDING_ACKS: usize = 1000;
8
9pub const DEFAULT_MAX_RETRIES: u32 = 10;
11
12pub const DEFAULT_INITIAL_DELAY_MS: u64 = 1000;
14
15pub const DEFAULT_MAX_DELAY_MS: u64 = 300_000;
24
25pub const DEFAULT_BACKOFF_MULTIPLIER: f32 = 2.0;
27
28pub const DEFAULT_OUTBOX_LIFETIME_MS: u64 = 604_800_000;
34
35pub const DEFAULT_PENDING_MESSAGE_LIFETIME_MS: u64 = 604_800_000;
40
41pub const ESTIMATED_ACK_SIZE_BYTES: usize = 40;
43
44pub const SMALL_NETWORK_RELAY_THRESHOLD: usize = 5;
46
47pub const RELAY_DENSITY_FACTOR_NUMERATOR: f32 = 5.0;
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
62 fn rn_bridge_retry_fallbacks_match_rust_defaults() {
63 let rn_root =
64 std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../bindings/react-native");
65 let kotlin_path =
66 rn_root.join("android/src/main/java/com/offlineprotocol/OfflineProtocolModule.kt");
67 let swift_path = rn_root.join("ios/OfflineProtocolModule.swift");
68
69 let (Ok(kotlin), Ok(swift)) = (
72 std::fs::read_to_string(&kotlin_path),
73 std::fs::read_to_string(&swift_path),
74 ) else {
75 eprintln!("bindings tree not present, skipping RN fallback drift check");
76 return;
77 };
78
79 let ack_expected = [
80 (
81 format!("json.optLong(\"defaultTimeoutMs\", {DEFAULT_ACK_TIMEOUT_MS})"),
82 format!(
83 "(config[\"defaultTimeoutMs\"] as? NSNumber)?.uint64Value ?? {DEFAULT_ACK_TIMEOUT_MS}"
84 ),
85 ),
86 (
87 format!("json.optLong(\"maxPendingAcks\", {DEFAULT_MAX_PENDING_ACKS})"),
88 format!(
89 "(config[\"maxPendingAcks\"] as? NSNumber)?.uint64Value ?? {DEFAULT_MAX_PENDING_ACKS}"
90 ),
91 ),
92 ];
93 for (kotlin_fallback, swift_fallback) in &ack_expected {
94 assert!(
95 kotlin.contains(kotlin_fallback),
96 "RN Android bridge ACK fallback drifted from the Rust default: \
97 expected `{kotlin_fallback}` in {}",
98 kotlin_path.display()
99 );
100 assert!(
101 swift.contains(swift_fallback),
102 "RN iOS bridge ACK fallback drifted from the Rust default: \
103 expected `{swift_fallback}` in {}",
104 swift_path.display()
105 );
106 }
107
108 let kotlin_expected = [
109 format!("json.optInt(\"maxRetries\", {DEFAULT_MAX_RETRIES})"),
110 format!("json.optLong(\"initialDelayMs\", {DEFAULT_INITIAL_DELAY_MS})"),
111 format!("json.optLong(\"maxDelayMs\", {DEFAULT_MAX_DELAY_MS})"),
112 format!("json.optDouble(\"backoffMultiplier\", {DEFAULT_BACKOFF_MULTIPLIER:.1})"),
113 format!("json.optLong(\"outboxMaxLifetimeMs\", {DEFAULT_OUTBOX_LIFETIME_MS})"),
114 format!(
115 "json.optLong(\"pendingMessageMaxLifetimeMs\", {DEFAULT_PENDING_MESSAGE_LIFETIME_MS})"
116 ),
117 ];
118 for expected in &kotlin_expected {
119 assert!(
120 kotlin.contains(expected),
121 "RN Android bridge retry fallback drifted from the Rust default: \
122 expected `{expected}` in {}",
123 kotlin_path.display()
124 );
125 }
126
127 let swift_expected = [
128 format!("(config[\"maxRetries\"] as? NSNumber)?.uint32Value ?? {DEFAULT_MAX_RETRIES}"),
129 format!(
130 "(config[\"initialDelayMs\"] as? NSNumber)?.uint64Value ?? {DEFAULT_INITIAL_DELAY_MS}"
131 ),
132 format!("(config[\"maxDelayMs\"] as? NSNumber)?.uint64Value ?? {DEFAULT_MAX_DELAY_MS}"),
133 format!(
134 "(config[\"backoffMultiplier\"] as? NSNumber)?.floatValue ?? {DEFAULT_BACKOFF_MULTIPLIER:.1}"
135 ),
136 format!(
137 "(config[\"outboxMaxLifetimeMs\"] as? NSNumber)?.uint64Value ?? {DEFAULT_OUTBOX_LIFETIME_MS}"
138 ),
139 format!(
140 "(config[\"pendingMessageMaxLifetimeMs\"] as? NSNumber)?.uint64Value ?? {DEFAULT_PENDING_MESSAGE_LIFETIME_MS}"
141 ),
142 ];
143 for expected in &swift_expected {
144 assert!(
145 swift.contains(expected),
146 "RN iOS bridge retry fallback drifted from the Rust default: \
147 expected `{expected}` in {}",
148 swift_path.display()
149 );
150 }
151 }
152}