From 517d5cf263bdbea232186636ce99e7c3be15d00f Mon Sep 17 00:00:00 2001 From: eunhhu Date: Fri, 25 Sep 2026 16:06:21 +0100 Subject: Save app changes in bursts A save now publishes everything since the last save in one commit: the documents messages edited and the states that changed. If it fails, every event since the last save is undone (values, text and list drafts, the list undo log, event and tick counts), so an event reported as successful is stored and a failed one leaves no trace. By default each key, text and message event saves before it returns, as before. With pure_app_defer events apply at once and a host saves a burst with one commit; a key's document joins a burst once, so revisions move one per save. On the Pi's SD card 600 events take 6.3 s saved one by one, 0.97 s in bursts of 8 and 0.34 s in bursts of 64. pure-run takes --batch N. Tests compare a deferred stored app that saves at random and sometimes stops unsaved with an app that replays only the saved events, undo a whole burst on a failed save, and kill a process while it saves a burst. --- prototypes/connections/module-save.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'prototypes/connections/module-save.c') diff --git a/prototypes/connections/module-save.c b/prototypes/connections/module-save.c index 40b3934..573ac3f 100644 --- a/prototypes/connections/module-save.c +++ b/prototypes/connections/module-save.c @@ -244,9 +244,15 @@ PureResult pure_save_open_values(PureApp *app, const PureModule *m, double *valu static bool same_version(PureVersion a, PureVersion b) { return a.ref == b.ref && a.bytes == b.bytes; } -PureResult pure_save_commit(PureApp *app, const double *values, void *document, int64_t *revision) { - if (!pure_save_enabled(app)) - return document ? app->data.commit(app->data.context, document, revision) : PURE_OK; +PureResult pure_save_commit(PureApp *app, const double *values, void *const *documents, size_t document_count, + int64_t *revisions) { + if (!pure_save_enabled(app)) { + /* Without a host that saves together, a save has one document at most. */ + PureResult result = PURE_OK; + for (size_t i = 0; i < document_count && result == PURE_OK; ++i) + result = app->data.commit(app->data.context, documents[i], &revisions[i]); + return result; + } const PureModule *m = app->module; PureDraft *drafts[2 * PURE_MODULE_STATES + 1]; uint32_t states[2 * PURE_MODULE_STATES + 1]; @@ -278,9 +284,8 @@ PureResult pure_save_commit(PureApp *app, const double *values, void *document, drafts[count++] = app->stored_values; } } - if (!count && !document) return PURE_OK; - int64_t ignored; - PureResult result = app->data.save(app->data.context, document, drafts, count, document ? revision : &ignored); + if (!count && !document_count) return PURE_OK; + PureResult result = app->data.save(app->data.context, documents, document_count, drafts, count, revisions); for (size_t k = 0; result == PURE_OK && k < count; ++k) if (states[k] != UINT32_MAX) app->saved[states[k]] = pure_draft_version(drafts[k]); if (values_changed) { -- cgit v1.2.3