1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! # RSP-RS
//!
//! A high-performance RDF Stream Processing engine in Rust, supporting RSP-QL queries
//! with sliding windows and real-time analytics.
//!
//! This library provides:
//! - RSP-QL syntax support for continuous queries
//! - Sliding and tumbling window semantics
//! - SPARQL aggregation functions (COUNT, AVG, MIN, MAX, SUM)
//! - Real-time stream processing with multi-threading
//! - Integration with static background knowledge
//!
//! ## When Are Results Emitted?
//!
//! **Important:** Results are emitted when windows **close**, which happens when:
//! 1. A new event arrives with a **timestamp** > window end time
//! 2. The window's STEP interval is reached **based on event timestamps**
//!
//! **Key Concept:** Window closure is driven by **event timestamps**, NOT wall-clock time!
//! The system doesn't use timers - it only processes events when you call `add_quads()`.
//!
//! ### Example with RANGE 10000 STEP 2000:
//!
//! ```text
//! - Events at t=0, 500, 1000, 1500 are added to windows
//! - No results yet (windows still open)
//! - Event with timestamp=2000 arrives -> closes window [-8000, 2000) -> results emitted
//! - Event with timestamp=4000 arrives -> closes window [-6000, 4000) -> results emitted
//!
//! Note: Wall-clock time doesn't matter! You could add all these events instantly,
//! but results only emit when an event's TIMESTAMP triggers window closure.
//! ```
//!
//! **Important:** If your last event has timestamp=1500, NO results will be emitted
//! because no subsequent event with a higher timestamp triggered window closure.
//! Use `close_stream()` to add a "sentinel" event with a future timestamp to trigger
//! remaining window closures.
//!
//! ### Complete Example with Stream Closure:
//!
//! ```rust,no_run
//! use rsp_rs::RSPEngine;
//! use oxigraph::model::*;
//!
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let query = r#"
//! PREFIX ex: <https://rsp.rs/>
//! REGISTER RStream <output> AS
//! SELECT *
//! FROM NAMED WINDOW ex:w1 ON STREAM ex:stream1 [RANGE 10000 STEP 2000]
//! WHERE {
//! WINDOW ex:w1 { ?s ?p ?o }
//! }
//! "#;
//!
//! let mut rsp_engine = RSPEngine::new(query.to_string());
//! rsp_engine.initialize()?;
//!
//! // Get a cloned stream (can be stored and reused)
//! let stream = rsp_engine.get_stream("https://rsp.rs/stream1").unwrap();
//!
//! // Start processing results
//! let result_receiver = rsp_engine.start_processing();
//!
//! // Add events with TIMESTAMPS (not wall-clock time!)
//! // These could be added instantly or over hours - doesn't matter
//! let quad1 = Quad::new(
//! NamedNode::new("https://rsp.rs/subject1")?,
//! NamedNode::new("https://rsp.rs/predicate")?,
//! NamedNode::new("https://rsp.rs/object")?,
//! GraphName::DefaultGraph,
//! );
//! stream.add_quads(vec![quad1], 1000)?; // timestamp = 1000
//!
//! let quad2 = Quad::new(
//! NamedNode::new("https://rsp.rs/subject2")?,
//! NamedNode::new("https://rsp.rs/predicate")?,
//! NamedNode::new("https://rsp.rs/object")?,
//! GraphName::DefaultGraph,
//! );
//! stream.add_quads(vec![quad2], 1500)?; // timestamp = 1500
//!
//! // IMPORTANT: Close the stream to emit final results
//! // This adds a sentinel event with timestamp=10000 to trigger window closures
//! rsp_engine.close_stream("https://rsp.rs/stream1", 10000)?;
//!
//! // Collect results
//! while let Ok(result) = result_receiver.recv() {
//! println!("Result: {} (window: {} to {})",
//! result.bindings,
//! result.timestamp_from,
//! result.timestamp_to);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ## Understanding Window Lifecycle
//!
//! Windows don't emit results when events arrive - they emit when **closed** by future events.
//!
//! **Critical:** The timeline below shows EVENT TIMESTAMPS (not wall-clock time):
//!
//! ### Timeline Example (RANGE 10s, STEP 2s):
//!
//! ```text
//! Event with timestamp=0: Added to window
//! Event with timestamp=1000: More events added to window
//! Event with timestamp=2000: -> window [-8000, 2000) closes -> RESULTS EMITTED
//! Event with timestamp=4000: -> window [-6000, 4000) closes -> RESULTS EMITTED
//! Event with timestamp=6000: -> window [-4000, 6000) closes -> RESULTS EMITTED
//! ...
//! Event with timestamp=15000: Last event added to stream
//! NO MORE RESULTS (no event to trigger closure!)
//!
//! Solution: Call close_stream("stream_uri", 20000) to emit final results
//!
//! Note: You can add ALL these events in 1 millisecond of real time! The system only
//! cares about the timestamps you provide, not how fast you send events.
//! ```
//!
//! ## Debugging Window Behavior
//!
//! You can inspect window state for debugging:
//!
//! ```rust,no_run
//! # use rsp_rs::RSPEngine;
//! # let mut engine = RSPEngine::new("".to_string());
//! # engine.initialize().unwrap();
//! if let Some(window) = engine.get_window("window_name") {
//! let window_lock = window.lock().unwrap();
//!
//! // Check how many windows are active
//! println!("Active windows: {}", window_lock.get_active_window_count());
//!
//! // See the time ranges of active windows
//! for (start, end) in window_lock.get_active_window_ranges() {
//! println!("Window: [{}, {})", start, end);
//! }
//!
//! // Enable verbose debug logging
//! // window_lock.set_debug_mode(true);
//! }
//! ```
// Re-export modules for easier access
pub use *;
pub use *;
pub use *;
// Public API exports
pub use R2ROperator;
pub use ;
pub use ;
pub use RSPQLParser;
pub use QuadContainer;
pub use ;
pub use WindowInstance;