aboutsummaryrefslogtreecommitdiffstats
path: root/src/state/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/mod.rs')
-rw-r--r--src/state/mod.rs33
1 files changed, 30 insertions, 3 deletions
diff --git a/src/state/mod.rs b/src/state/mod.rs
index ef1559d..1fc8ea8 100644
--- a/src/state/mod.rs
+++ b/src/state/mod.rs
@@ -38,7 +38,7 @@ use tracing::{debug, error, warn};
use crate::document::lock::DocumentLock;
use crate::document::replica::{Epoch, Stamp};
-use crate::document::signatures::Sign;
+use crate::document::signatures::{Sign, SignEvery};
use crate::document::store::{ChangeSet, StoreError};
use crate::document::{Document, Transaction};
use crate::locks::{MutexExt, RwLockExt};
@@ -147,6 +147,9 @@ pub(crate) struct AppState {
/// Signs the tokens this node issues and the changes it commits
/// (`NodeConfig::node_key`).
pub(crate) node_key: Option<Arc<crate::identity::NodeKey>>,
+ /// Which of its changes this node signs besides those a write's `Sign` says
+ /// (`--sign-every`).
+ pub(crate) sign_every: SignEvery,
pub(crate) token_lifetime: Duration,
pub(crate) session_lifetime: Duration,
/// Origins whose pages may call this node's open endpoints (`api::cors`).
@@ -527,9 +530,12 @@ impl AppState {
let after = replica.doc.get_heads();
if after != before
&& let [hash] = after[..]
- && sign.wanted(&replica.doc)
{
- replica.signatures.sign(hash, key);
+ if state.sign_every == SignEvery::Change || sign.wanted(&replica.doc) {
+ replica.signatures.sign(hash, key);
+ } else {
+ replica.signatures.left_unsigned(hash);
+ }
}
}
replica.refresh_heads();
@@ -545,6 +551,27 @@ impl AppState {
.expect("document write task panicked")
}
+ /// This node's latest change signed, if no signature vouches for it yet, every
+ /// `every` (`--sign-every`): every change it makes is vouched for within that.
+ pub(crate) async fn sign_latest_every(self, every: Duration) {
+ let Some(key) = self.node_key.clone() else {
+ return;
+ };
+ let mut ticks = tokio::time::interval(every);
+ ticks.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
+ loop {
+ ticks.tick().await;
+ let state = self.clone();
+ let key = Arc::clone(&key);
+ let _ = tokio::task::spawn_blocking(move || {
+ // Looked at first under the read lock: mostly there is nothing to sign.
+ state.doc.blocking_read().signatures.pending()
+ && state.doc.blocking_write().signatures.sign_latest(&key)
+ })
+ .await;
+ }
+ }
+
pub(crate) fn publish_change(&self) {
self.notify_store_changed();
if let Err(error) = self.sync_events.send(SyncEvent::DocumentChanged) {