Feat: Include record ID in live queries notifications. (#2950)

Co-authored-by: Tobie Morgan Hitchcock <tobie@surrealdb.com>
This commit is contained in:
Roman Heinrich 2024-09-16 01:48:57 +02:00 committed by GitHub
parent 218fa83c10
commit be24734048
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 21 additions and 10 deletions

View file

@ -33,6 +33,8 @@ pub struct Notification {
pub id: Uuid,
/// The CREATE / UPDATE / DELETE action which caused this notification
pub action: Action,
/// The id of the document to which this notification has been made
pub record: Value,
/// The resulting notification content, usually the altered record content
pub result: Value,
}
@ -42,6 +44,7 @@ impl Display for Notification {
let obj: Object = map! {
"id".to_string() => self.id.to_string().into(),
"action".to_string() => self.action.to_string().into(),
"record".to_string() => self.record.clone(),
"result".to_string() => self.result.clone(),
}
.into();
@ -51,10 +54,11 @@ impl Display for Notification {
impl Notification {
/// Construct a new notification
pub const fn new(id: Uuid, action: Action, result: Value) -> Self {
pub const fn new(id: Uuid, action: Action, record: Value, result: Value) -> Self {
Self {
id,
action,
record,
result,
}
}
@ -63,6 +67,6 @@ impl Notification {
#[cfg(test)]
impl FuzzyEq for Notification {
fn fuzzy_eq(&self, other: &Self) -> bool {
self.action == other.action && self.result == other.result
self.action == other.action && self.record == other.record && self.result == other.result
}
}

View file

@ -47,6 +47,9 @@ impl Document {
} else {
Value::from("UPDATE")
};
// Get the record if of this docunent
let rid = self.id.as_ref().unwrap();
// Get the current and initial docs
let current = self.current.doc.as_arc();
let initial = self.initial.doc.as_arc();
// Check if this is a delete statement
@ -119,6 +122,7 @@ impl Document {
chn.send(Notification {
id: lv.id,
action: Action::Delete,
record: Value::Thing(rid.as_ref().clone()),
result: {
// Ensure futures are run
let lqopt: &Options = &lqopt.new_with_futures(true);
@ -141,6 +145,7 @@ impl Document {
chn.send(Notification {
id: lv.id,
action: Action::Create,
record: Value::Thing(rid.as_ref().clone()),
result: self.pluck(stk, &lqctx, &lqopt, &lq).await?,
})
.await?;
@ -153,6 +158,7 @@ impl Document {
chn.send(Notification {
id: lv.id,
action: Action::Update,
record: Value::Thing(rid.as_ref().clone()),
result: self.pluck(stk, &lqctx, &lqopt, &lq).await?,
})
.await?;

View file

@ -162,6 +162,7 @@ mod tests {
use crate::kvs::Datastore;
use crate::kvs::LockType::Optimistic;
use crate::kvs::TransactionType::Write;
use crate::sql::Thing;
use crate::sql::Value;
use crate::syn::Parse;
@ -202,15 +203,14 @@ mod tests {
tx.cancel().await.unwrap();
// Initiate a Create record
let create_statement = format!("CREATE {}:test_true SET condition = true", tb);
let create_statement = format!("CREATE {tb}:test_true SET condition = true");
let create_response = &mut dbs.execute(&create_statement, &ses, None).await.unwrap();
assert_eq!(create_response.len(), 1);
let expected_record = Value::parse(&format!(
"[{{
id: {}:test_true,
id: {tb}:test_true,
condition: true,
}}]",
tb
}}]"
));
let tmp = create_response.remove(0).result.unwrap();
@ -231,12 +231,12 @@ mod tests {
Notification::new(
live_id,
Action::Create,
Value::Thing(Thing::from((tb, "test_true"))),
Value::parse(&format!(
"{{
id: {}:test_true,
id: {tb}:test_true,
condition: true,
}}",
tb
}}"
),),
)
);

View file

@ -416,6 +416,7 @@ async fn delete_filtered_live_notification() -> Result<(), Error> {
Notification::new(
live_id,
Action::Delete,
Value::Thing(Thing::from(("person", "test_true"))),
Value::parse(
"{
id: person:test_true,

View file

@ -24,7 +24,7 @@ pub fn is_notification(msg: &serde_json::Value) -> bool {
.as_object()
.unwrap()
.keys()
.all(|k| ["id", "action", "result"].contains(&k.as_str()))
.all(|k| ["id", "action", "record", "result"].contains(&k.as_str()))
}
/// Check if the given message is a notification from LQ and comes from the given LQ ID.