update
This commit is contained in:
@@ -6,11 +6,19 @@ import {readJson, writeJson} from './store.js';
|
||||
|
||||
// Abgleich mit dem Server. Zugang steht in sync.json im Datenordner:
|
||||
// {"url": "https://planer.marha.de", "token": "...", "interval": 5}
|
||||
// Alle paar Sekunden und kurz nach jeder eigenen Änderung: eigene Änderungen hochladen,
|
||||
// Änderungen des Servers seit dem letzten Stand holen. Bei Konflikten gewinnt der Eintrag mit dem neueren updated.
|
||||
// Kurz nach jeder eigenen Änderung und in einem Takt, der sich nach der Aktivität richtet:
|
||||
// eigene Änderungen hochladen, Änderungen des Servers seit dem letzten Stand holen.
|
||||
// Bei Konflikten gewinnt der Eintrag mit dem neueren updated.
|
||||
// sync-state.json merkt sich den Server-Stand (cursor) und was zuletzt übertragen wurde (pushed).
|
||||
|
||||
const DEFAULT_INTERVAL = 5;
|
||||
// Takt nach der letzten Aktivität (eigene Änderung oder Änderung vom Server):
|
||||
// erste Minute jede Sekunde, dann alle 5 Sekunden, nach 5 Minuten Ruhe alle 10 Sekunden.
|
||||
// "interval" in sync.json ersetzt den Ruhetakt.
|
||||
const INTERVALS = [
|
||||
{after: 0, seconds: 1},
|
||||
{after: 60, seconds: 5},
|
||||
{after: 5 * 60, seconds: 10},
|
||||
];
|
||||
// Kurze Wartezeit nach einer eigenen Änderung, damit mehrere Klicks in einem Lauf landen
|
||||
const SOON_MS = 500;
|
||||
|
||||
@@ -32,6 +40,8 @@ export class Sync {
|
||||
this._timerId = null;
|
||||
this._soonId = null;
|
||||
this._applying = false;
|
||||
// Beim Start gilt: lange nichts passiert
|
||||
this._lastActivity = 0;
|
||||
}
|
||||
|
||||
get active() {
|
||||
@@ -41,18 +51,40 @@ export class Sync {
|
||||
start() {
|
||||
if (!this.active)
|
||||
return;
|
||||
const interval = this._config.interval ?? DEFAULT_INTERVAL;
|
||||
this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, interval, () => {
|
||||
this._cycle().catch(e => this._fail(e.message));
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
});
|
||||
// Eigene Änderungen gehen sofort raus, nicht erst beim nächsten Takt
|
||||
this._store.onChange(() => this._scheduleSoon());
|
||||
this._cycle().catch(e => this._fail(e.message));
|
||||
this._scheduleNext();
|
||||
}
|
||||
|
||||
// Aktueller Takt in Sekunden, je nachdem wie lange die letzte Aktivität her ist.
|
||||
get interval() {
|
||||
const idle = (GLib.get_monotonic_time() - this._lastActivity) / 1e6;
|
||||
const step = [...INTERVALS].reverse().find(s => idle >= s.after);
|
||||
const idleInterval = this._config.interval ?? INTERVALS.at(-1).seconds;
|
||||
return step === INTERVALS.at(-1) ? idleInterval : step.seconds;
|
||||
}
|
||||
|
||||
_touchActivity() {
|
||||
this._lastActivity = GLib.get_monotonic_time();
|
||||
}
|
||||
|
||||
// Nächsten Lauf planen. Der Abstand wird jedes Mal neu bestimmt.
|
||||
_scheduleNext() {
|
||||
if (this._stopped)
|
||||
return;
|
||||
this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, this.interval, () => {
|
||||
this._timerId = null;
|
||||
this._cycle().catch(e => this._fail(e.message)).finally(() => this._scheduleNext());
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
_scheduleSoon() {
|
||||
if (this._stopped || this._applying || this._soonId)
|
||||
if (this._stopped || this._applying)
|
||||
return;
|
||||
this._touchActivity();
|
||||
if (this._soonId)
|
||||
return;
|
||||
this._soonId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SOON_MS, () => {
|
||||
this._soonId = null;
|
||||
@@ -82,6 +114,9 @@ export class Sync {
|
||||
try {
|
||||
const payload = this._collect();
|
||||
const response = await this._post(payload);
|
||||
// Kam etwas vom Server, ist das andere Gerät gerade aktiv: schneller nachfragen
|
||||
if (['events', 'todos', 'notes', 'folders'].some(c => (response[c] ?? []).length))
|
||||
this._touchActivity();
|
||||
// Übernommene Änderungen lösen selbst onChange aus, das soll keinen neuen Lauf starten
|
||||
this._applying = true;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user