use serde::{Deserialize, Serialize};
use serde_json::Value as Json;
use uuid::Uuid;
use crate::clock::TimestampMs;
use crate::hlc::Hlc;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "op", rename_all = "snake_case")]
pub enum GraphOp {
AddNode {
id: Uuid,
kind: String,
name: String,
#[serde(default)]
summary: String,
#[serde(default = "empty_object")]
attrs: Json,
#[serde(default)]
group_id: String,
},
AddEdge {
id: Uuid,
src: Uuid,
dst: Uuid,
rel: String,
#[serde(default)]
fact: String,
#[serde(default = "empty_object")]
attrs: Json,
#[serde(default)]
group_id: String,
#[serde(default)]
valid_at: Option<TimestampMs>,
#[serde(default)]
invalid_at: Option<TimestampMs>,
},
AddEpisode {
id: Uuid,
source: String,
#[serde(default)]
kind: String,
content: String,
occurred_at: TimestampMs,
#[serde(default)]
group_id: String,
#[serde(default)]
mentions: Vec<Uuid>,
},
UpdateNode {
id: Uuid,
#[serde(default, skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
summary: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
attrs: Option<Json>,
},
InvalidateEdge {
edge_id: Uuid,
invalid_at: TimestampMs,
},
MergeNodes {
from: Uuid,
into: Uuid,
},
Purge {
ids: Vec<Uuid>,
},
}
fn empty_object() -> Json {
Json::Object(serde_json::Map::new())
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OplogEntry {
pub id: Uuid,
pub hlc: Hlc,
pub device_id: String,
pub op: GraphOp,
}