Skip to main content

velesdb_server/handlers/graph/
types.rs

1//! Graph types for VelesDB REST API.
2//!
3//! Contains request/response types for graph operations.
4
5use serde::{Deserialize, Serialize};
6use utoipa::{IntoParams, ToSchema};
7use velesdb_core::api_types::serde_id;
8
9/// A single traversal result item.
10#[derive(Debug, Clone, Serialize, ToSchema)]
11pub struct TraversalResultItem {
12    /// Target node ID reached.
13    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
14    pub target_id: u64,
15    /// Depth of traversal (number of hops from source).
16    pub depth: u32,
17    /// Path taken (list of edge IDs).
18    pub path: Vec<u64>,
19}
20
21/// Query parameters for edge operations.
22#[derive(Debug, Deserialize, IntoParams)]
23pub struct EdgeQueryParams {
24    /// Filter edges by label (e.g., "KNOWS", "FOLLOWS").
25    #[param(example = "KNOWS")]
26    pub label: Option<String>,
27}
28
29/// Request for graph traversal.
30#[derive(Debug, Deserialize, ToSchema)]
31pub struct TraverseRequest {
32    /// Source node ID to start traversal from.
33    #[serde(deserialize_with = "serde_id::deserialize_id_from_string_or_number")]
34    pub source: u64,
35    /// Traversal strategy: "bfs" or "dfs".
36    #[serde(default = "default_strategy")]
37    pub strategy: String,
38    /// Maximum traversal depth.
39    #[serde(default = "default_max_depth")]
40    pub max_depth: u32,
41    /// Maximum number of results to return.
42    #[serde(default = "default_limit")]
43    pub limit: usize,
44    /// Filter by relationship types (empty = all types).
45    #[serde(default)]
46    pub rel_types: Vec<String>,
47}
48
49fn default_strategy() -> String {
50    "bfs".to_string()
51}
52
53fn default_max_depth() -> u32 {
54    3
55}
56
57fn default_limit() -> usize {
58    100
59}
60
61/// Response from graph traversal.
62#[derive(Debug, Serialize, ToSchema)]
63pub struct TraverseResponse {
64    /// List of traversal results.
65    pub results: Vec<TraversalResultItem>,
66    /// Whether more results are available.
67    pub has_more: bool,
68    /// Traversal statistics.
69    pub stats: TraversalStats,
70}
71
72/// Statistics from traversal operation.
73#[derive(Debug, Serialize, ToSchema)]
74pub struct TraversalStats {
75    /// Number of nodes visited.
76    pub visited: usize,
77    /// Maximum depth reached.
78    pub depth_reached: u32,
79}
80
81/// Response for node degree query.
82#[derive(Debug, Serialize, ToSchema)]
83pub struct DegreeResponse {
84    /// Number of incoming edges.
85    pub in_degree: usize,
86    /// Number of outgoing edges.
87    pub out_degree: usize,
88}
89
90/// Response containing edges.
91#[derive(Debug, Serialize, ToSchema)]
92pub struct EdgesResponse {
93    /// List of edges.
94    pub edges: Vec<EdgeResponse>,
95    /// Total count of edges returned.
96    pub count: usize,
97}
98
99/// A single edge in the response.
100#[derive(Debug, Serialize, ToSchema)]
101pub struct EdgeResponse {
102    /// Edge ID.
103    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
104    pub id: u64,
105    /// Source node ID.
106    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
107    pub source: u64,
108    /// Target node ID.
109    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
110    pub target: u64,
111    /// Edge label (relationship type).
112    pub label: String,
113    /// Edge properties.
114    pub properties: serde_json::Value,
115}
116
117/// Request to add an edge to the graph.
118#[derive(Debug, Deserialize, ToSchema)]
119pub struct AddEdgeRequest {
120    /// Edge ID.
121    #[serde(deserialize_with = "serde_id::deserialize_id_from_string_or_number")]
122    pub id: u64,
123    /// Source node ID.
124    #[serde(deserialize_with = "serde_id::deserialize_id_from_string_or_number")]
125    pub source: u64,
126    /// Target node ID.
127    #[serde(deserialize_with = "serde_id::deserialize_id_from_string_or_number")]
128    pub target: u64,
129    /// Edge label (relationship type).
130    pub label: String,
131    /// Edge properties.
132    #[serde(default)]
133    pub properties: serde_json::Value,
134}
135
136// ============================================================================
137// Edge Count, Node List, Node Payload, Parallel Traversal, Graph Search
138// ============================================================================
139
140/// Response for edge count query.
141#[derive(Debug, Serialize, ToSchema)]
142pub struct EdgeCountResponse {
143    /// Total number of edges in the graph.
144    pub count: usize,
145}
146
147/// Query parameters for node-scoped edge queries.
148#[derive(Debug, Deserialize, IntoParams)]
149pub struct NodeEdgeQueryParams {
150    /// Filter by direction: "in", "out", or "both".
151    #[serde(default = "default_direction")]
152    #[param(example = "out")]
153    pub direction: String,
154    /// Filter edges by label.
155    #[param(example = "KNOWS")]
156    pub label: Option<String>,
157}
158
159fn default_direction() -> String {
160    "out".to_string()
161}
162
163/// Response containing all node IDs in the graph.
164#[derive(Debug, Serialize, ToSchema)]
165pub struct NodeListResponse {
166    /// List of node IDs.
167    pub node_ids: Vec<u64>,
168    /// Total count of nodes.
169    pub count: usize,
170}
171
172/// Request to upsert a node payload.
173#[derive(Debug, Deserialize, ToSchema)]
174pub struct UpsertNodePayloadRequest {
175    /// JSON payload to store on the node.
176    pub payload: serde_json::Value,
177}
178
179/// Response for a node payload retrieval.
180#[derive(Debug, Serialize, ToSchema)]
181pub struct NodePayloadResponse {
182    /// Node ID.
183    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
184    pub node_id: u64,
185    /// Stored payload (null if none).
186    pub payload: Option<serde_json::Value>,
187}
188
189/// Request for parallel multi-source BFS traversal.
190#[derive(Debug, Deserialize, ToSchema)]
191pub struct ParallelTraverseRequest {
192    /// Source node IDs to start traversal from.
193    pub sources: Vec<u64>,
194    /// Maximum traversal depth.
195    #[serde(default = "default_max_depth")]
196    pub max_depth: u32,
197    /// Maximum number of results per source.
198    #[serde(default = "default_limit")]
199    pub limit: usize,
200    /// Filter by relationship types (empty = all types).
201    #[serde(default)]
202    pub rel_types: Vec<String>,
203}
204
205/// Request for graph embedding search.
206#[derive(Debug, Deserialize, ToSchema)]
207pub struct GraphSearchRequest {
208    /// Query vector for similarity search.
209    pub vector: Vec<f32>,
210    /// Number of results to return.
211    #[serde(default = "default_graph_search_k")]
212    pub top_k: usize,
213}
214
215fn default_graph_search_k() -> usize {
216    10
217}
218
219/// Response for graph embedding search.
220#[derive(Debug, Serialize, ToSchema)]
221pub struct GraphSearchResponse {
222    /// Search results with node ID and similarity score.
223    pub results: Vec<GraphSearchResultItem>,
224}
225
226/// A single graph search result.
227#[derive(Debug, Serialize, ToSchema)]
228pub struct GraphSearchResultItem {
229    /// Node ID.
230    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
231    pub id: u64,
232    /// Similarity score.
233    pub score: f32,
234    /// Node payload (if any).
235    pub payload: Option<serde_json::Value>,
236}
237
238// ============================================================================
239// SSE Streaming Types (EPIC-058 US-003)
240// ============================================================================
241
242/// Query parameters for streaming graph traversal.
243#[derive(Debug, Deserialize, IntoParams)]
244pub struct StreamTraverseParams {
245    /// Source node ID to start traversal from.
246    #[serde(deserialize_with = "serde_id::deserialize_id_from_string_or_number")]
247    #[param(example = 123)]
248    pub start_node: u64,
249    /// Traversal algorithm: "bfs" or "dfs".
250    #[serde(default = "default_algorithm")]
251    #[param(example = "bfs")]
252    pub algorithm: String,
253    /// Maximum traversal depth.
254    #[serde(default = "default_stream_max_depth")]
255    #[param(example = 5)]
256    pub max_depth: u32,
257    /// Maximum number of results to stream.
258    #[serde(default = "default_stream_limit")]
259    #[param(example = 1000)]
260    pub limit: usize,
261    /// Filter by relationship types (comma-separated).
262    #[serde(default)]
263    #[param(example = "KNOWS,FOLLOWS")]
264    pub relationship_types: Option<String>,
265}
266
267fn default_algorithm() -> String {
268    "bfs".to_string()
269}
270
271fn default_stream_max_depth() -> u32 {
272    5
273}
274
275fn default_stream_limit() -> usize {
276    1000
277}
278
279/// SSE event: A node reached during traversal.
280#[derive(Debug, Serialize, ToSchema)]
281pub struct StreamNodeEvent {
282    /// Target node ID.
283    #[serde(serialize_with = "serde_id::serialize_id_as_string")]
284    pub id: u64,
285    /// Depth from source.
286    pub depth: u32,
287    /// Path of edge IDs taken to reach this node.
288    pub path: Vec<u64>,
289}
290
291/// SSE event: Periodic statistics update.
292#[derive(Debug, Serialize, ToSchema)]
293pub struct StreamStatsEvent {
294    /// Number of nodes visited so far.
295    pub nodes_visited: usize,
296    /// Elapsed time in milliseconds.
297    pub elapsed_ms: u64,
298}
299
300/// SSE event: Traversal completed.
301#[derive(Debug, Serialize, ToSchema)]
302pub struct StreamDoneEvent {
303    /// Total nodes returned.
304    pub total_nodes: usize,
305    /// Maximum depth reached.
306    pub max_depth_reached: u32,
307    /// Total elapsed time in milliseconds.
308    pub elapsed_ms: u64,
309}
310
311/// SSE event: Error occurred.
312#[derive(Debug, Serialize, ToSchema)]
313pub struct StreamErrorEvent {
314    /// Error message.
315    pub error: String,
316}