Skip to main content

syncular_runtime/core/
limits.rs

1use serde::Serialize;
2
3use crate::error::{Result, SyncularError};
4use crate::store::{
5    BLOB_UPLOAD_STALE_TIMEOUT_MS, MAX_BLOB_UPLOAD_RETRIES, MAX_SYNC_RETRIES,
6    SQLITE_BUSY_TIMEOUT_MS, SYNC_SENDING_TIMEOUT_MS,
7};
8
9pub const DEFAULT_WORKER_COMMAND_QUEUE_CAPACITY: usize = 1024;
10pub const DEFAULT_WORKER_EVENT_QUEUE_CAPACITY: usize = 1024;
11pub const DEFAULT_NATIVE_EVENT_STREAM_CAPACITY: usize = 256;
12pub const DEFAULT_NATIVE_RECENT_EVENT_LIMIT: usize = 100;
13pub const DEFAULT_READONLY_QUERY_STATEMENT_CACHE_CAPACITY: usize = 64;
14
15pub const DEFAULT_PULL_LIMIT_COMMITS: i64 = 1000;
16pub const DEFAULT_PULL_LIMIT_SNAPSHOT_ROWS: i64 = 50_000;
17pub const DEFAULT_PULL_MAX_SNAPSHOT_PAGES: i64 = 10;
18pub const DEFAULT_OUTBOX_PUSH_BATCH_LIMIT: i64 = 20;
19pub const DEFAULT_ADAPTIVE_OUTBOX_PUSH_BATCH_LIMIT: i64 = MAX_OUTBOX_PUSH_BATCH_LIMIT;
20pub const DEFAULT_ADAPTIVE_OUTBOX_PUSH_THRESHOLD: i64 = 100;
21pub const MAX_OUTBOX_PUSH_BATCH_LIMIT: i64 = 1000;
22pub const DEFAULT_MAX_UNRESOLVED_OUTBOX_COMMITS: usize = 10_000;
23pub const DEFAULT_BLOB_UPLOAD_BATCH_LIMIT: i64 = 10;
24
25pub const DEFAULT_CRDT_STATE_VECTOR_HINT_LIMIT: i64 = 256;
26pub const DEFAULT_CRDT_UPDATE_QUEUE_CAPACITY: i64 = 1024;
27pub const DEFAULT_CRDT_UPDATE_LOG_LIMIT: i64 = 100;
28
29pub const DEFAULT_YJS_FLUSH_WINDOW_MS: u64 = 12;
30
31pub const MAX_SUBSCRIPTIONS_PER_CLIENT: usize = 256;
32pub const MAX_SCOPE_KEYS_PER_SUBSCRIPTION: usize = 16;
33pub const MAX_SCOPE_VALUES_PER_SUBSCRIPTION: usize = 4096;
34pub const MAX_SCOPE_VALUES_PER_CLIENT: usize = 16_384;
35pub const MAX_SUBSCRIPTION_PARAMS_PER_SUBSCRIPTION: usize = 32;
36pub const MAX_MUTATION_OPERATION_JSON_BYTES: usize = 1024 * 1024;
37pub const MAX_MUTATION_LOCAL_ROW_JSON_BYTES: usize = 1024 * 1024;
38pub const MAX_MUTATION_BATCH_JSON_BYTES: usize = 4 * 1024 * 1024;
39pub const MAX_OUTBOX_OPERATIONS_JSON_BYTES: usize = 4 * 1024 * 1024;
40pub const MAX_BLOB_PAYLOAD_BYTES: i64 = 64 * 1024 * 1024;
41pub const MAX_CRDT_REQUEST_JSON_BYTES: usize = 4 * 1024 * 1024;
42pub const MAX_CRDT_UPDATE_BASE64_BYTES: usize = 1024 * 1024;
43pub const MAX_CRDT_STATE_BASE64_BYTES: usize = 4 * 1024 * 1024;
44pub const MAX_CRDT_STATE_VECTOR_BASE64_BYTES: usize = 64 * 1024;
45pub const MAX_CRDT_TEXT_BYTES: usize = 1024 * 1024;
46pub const MAX_NATIVE_DIAGNOSTIC_EVENT_PAYLOAD_JSON_BYTES: usize = 16 * 1024;
47pub const MAX_SNAPSHOT_CHUNK_COMPRESSED_BYTES: i64 = 64 * 1024 * 1024;
48pub const MAX_SNAPSHOT_CHUNK_DECOMPRESSED_BYTES: usize = 256 * 1024 * 1024;
49pub const MAX_SNAPSHOT_ARTIFACT_COMPRESSED_BYTES: i64 = 256 * 1024 * 1024;
50pub const MAX_SNAPSHOT_ARTIFACT_DECOMPRESSED_BYTES: usize = 512 * 1024 * 1024;
51pub const MAX_REALTIME_SYNC_PACK_BYTES: usize = 16 * 1024 * 1024;
52pub const MAX_WEBSOCKET_TEXT_FRAME_BYTES: usize = 8 * 1024 * 1024;
53
54#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
55#[serde(rename_all = "camelCase")]
56pub struct RuntimeLimits {
57    pub worker_command_queue_capacity: usize,
58    pub worker_event_queue_capacity: usize,
59    pub native_default_event_stream_capacity: usize,
60    pub native_recent_event_limit: usize,
61    pub readonly_query_statement_cache_capacity: usize,
62    pub pull_limit_commits: i64,
63    pub pull_limit_snapshot_rows: i64,
64    pub pull_max_snapshot_pages: i64,
65    pub outbox_push_batch_limit: i64,
66    pub adaptive_outbox_push_batch_limit: i64,
67    pub adaptive_outbox_push_threshold: i64,
68    pub max_unresolved_outbox_commits: usize,
69    pub max_sync_retries: i32,
70    pub sync_sending_timeout_ms: i64,
71    pub max_blob_upload_retries: i32,
72    pub blob_upload_stale_timeout_ms: i64,
73    pub blob_upload_batch_limit: i64,
74    pub sqlite_busy_timeout_ms: i32,
75    pub crdt_state_vector_hint_limit: i64,
76    pub crdt_update_queue_capacity: i64,
77    pub crdt_update_log_default_limit: i64,
78    pub yjs_flush_window_ms: u64,
79    pub max_subscriptions_per_client: usize,
80    pub max_scope_keys_per_subscription: usize,
81    pub max_scope_values_per_subscription: usize,
82    pub max_scope_values_per_client: usize,
83    pub max_subscription_params_per_subscription: usize,
84    pub max_mutation_operation_json_bytes: usize,
85    pub max_mutation_local_row_json_bytes: usize,
86    pub max_mutation_batch_json_bytes: usize,
87    pub max_outbox_operations_json_bytes: usize,
88    pub max_blob_payload_bytes: i64,
89    pub max_crdt_request_json_bytes: usize,
90    pub max_crdt_update_base64_bytes: usize,
91    pub max_crdt_state_base64_bytes: usize,
92    pub max_crdt_state_vector_base64_bytes: usize,
93    pub max_crdt_text_bytes: usize,
94    pub max_native_diagnostic_event_payload_json_bytes: usize,
95    pub max_snapshot_chunk_compressed_bytes: i64,
96    pub max_snapshot_chunk_decompressed_bytes: usize,
97    pub max_snapshot_artifact_compressed_bytes: i64,
98    pub max_snapshot_artifact_decompressed_bytes: usize,
99    pub max_realtime_sync_pack_bytes: usize,
100    pub max_websocket_text_frame_bytes: usize,
101}
102
103pub fn runtime_default_limits() -> RuntimeLimits {
104    RuntimeLimits {
105        worker_command_queue_capacity: DEFAULT_WORKER_COMMAND_QUEUE_CAPACITY,
106        worker_event_queue_capacity: DEFAULT_WORKER_EVENT_QUEUE_CAPACITY,
107        native_default_event_stream_capacity: DEFAULT_NATIVE_EVENT_STREAM_CAPACITY,
108        native_recent_event_limit: DEFAULT_NATIVE_RECENT_EVENT_LIMIT,
109        readonly_query_statement_cache_capacity: DEFAULT_READONLY_QUERY_STATEMENT_CACHE_CAPACITY,
110        pull_limit_commits: DEFAULT_PULL_LIMIT_COMMITS,
111        pull_limit_snapshot_rows: DEFAULT_PULL_LIMIT_SNAPSHOT_ROWS,
112        pull_max_snapshot_pages: DEFAULT_PULL_MAX_SNAPSHOT_PAGES,
113        outbox_push_batch_limit: DEFAULT_OUTBOX_PUSH_BATCH_LIMIT,
114        adaptive_outbox_push_batch_limit: DEFAULT_ADAPTIVE_OUTBOX_PUSH_BATCH_LIMIT,
115        adaptive_outbox_push_threshold: DEFAULT_ADAPTIVE_OUTBOX_PUSH_THRESHOLD,
116        max_unresolved_outbox_commits: DEFAULT_MAX_UNRESOLVED_OUTBOX_COMMITS,
117        max_sync_retries: MAX_SYNC_RETRIES,
118        sync_sending_timeout_ms: SYNC_SENDING_TIMEOUT_MS,
119        max_blob_upload_retries: MAX_BLOB_UPLOAD_RETRIES,
120        blob_upload_stale_timeout_ms: BLOB_UPLOAD_STALE_TIMEOUT_MS,
121        blob_upload_batch_limit: DEFAULT_BLOB_UPLOAD_BATCH_LIMIT,
122        sqlite_busy_timeout_ms: SQLITE_BUSY_TIMEOUT_MS,
123        crdt_state_vector_hint_limit: DEFAULT_CRDT_STATE_VECTOR_HINT_LIMIT,
124        crdt_update_queue_capacity: DEFAULT_CRDT_UPDATE_QUEUE_CAPACITY,
125        crdt_update_log_default_limit: DEFAULT_CRDT_UPDATE_LOG_LIMIT,
126        yjs_flush_window_ms: DEFAULT_YJS_FLUSH_WINDOW_MS,
127        max_subscriptions_per_client: MAX_SUBSCRIPTIONS_PER_CLIENT,
128        max_scope_keys_per_subscription: MAX_SCOPE_KEYS_PER_SUBSCRIPTION,
129        max_scope_values_per_subscription: MAX_SCOPE_VALUES_PER_SUBSCRIPTION,
130        max_scope_values_per_client: MAX_SCOPE_VALUES_PER_CLIENT,
131        max_subscription_params_per_subscription: MAX_SUBSCRIPTION_PARAMS_PER_SUBSCRIPTION,
132        max_mutation_operation_json_bytes: MAX_MUTATION_OPERATION_JSON_BYTES,
133        max_mutation_local_row_json_bytes: MAX_MUTATION_LOCAL_ROW_JSON_BYTES,
134        max_mutation_batch_json_bytes: MAX_MUTATION_BATCH_JSON_BYTES,
135        max_outbox_operations_json_bytes: MAX_OUTBOX_OPERATIONS_JSON_BYTES,
136        max_blob_payload_bytes: MAX_BLOB_PAYLOAD_BYTES,
137        max_crdt_request_json_bytes: MAX_CRDT_REQUEST_JSON_BYTES,
138        max_crdt_update_base64_bytes: MAX_CRDT_UPDATE_BASE64_BYTES,
139        max_crdt_state_base64_bytes: MAX_CRDT_STATE_BASE64_BYTES,
140        max_crdt_state_vector_base64_bytes: MAX_CRDT_STATE_VECTOR_BASE64_BYTES,
141        max_crdt_text_bytes: MAX_CRDT_TEXT_BYTES,
142        max_native_diagnostic_event_payload_json_bytes:
143            MAX_NATIVE_DIAGNOSTIC_EVENT_PAYLOAD_JSON_BYTES,
144        max_snapshot_chunk_compressed_bytes: MAX_SNAPSHOT_CHUNK_COMPRESSED_BYTES,
145        max_snapshot_chunk_decompressed_bytes: MAX_SNAPSHOT_CHUNK_DECOMPRESSED_BYTES,
146        max_snapshot_artifact_compressed_bytes: MAX_SNAPSHOT_ARTIFACT_COMPRESSED_BYTES,
147        max_snapshot_artifact_decompressed_bytes: MAX_SNAPSHOT_ARTIFACT_DECOMPRESSED_BYTES,
148        max_realtime_sync_pack_bytes: MAX_REALTIME_SYNC_PACK_BYTES,
149        max_websocket_text_frame_bytes: MAX_WEBSOCKET_TEXT_FRAME_BYTES,
150    }
151}
152
153pub fn validate_unresolved_outbox_capacity(unresolved_count: usize) -> Result<()> {
154    if unresolved_count >= DEFAULT_MAX_UNRESOLVED_OUTBOX_COMMITS {
155        return Err(SyncularError::limit_exceeded(
156            "maxUnresolvedOutboxCommits",
157            unresolved_count,
158            DEFAULT_MAX_UNRESOLVED_OUTBOX_COMMITS,
159            "unresolved outbox queue is full",
160        ));
161    }
162    Ok(())
163}