Offline-Funktionen und spätere Synchronisierung planen
Gespeicherte Arbeit, eindeutige Übertragungsabsicht und passende Serverbestätigung als gemeinsamen Datenvertrag planen.

Offline beginnt mit einer ausdrücklich erlaubten Aufgabe
Offline-Funktionen erlauben eine sinnvolle Arbeit ohne aktuelle Verbindung. Spätere Synchronisierung muss zusätzlich klären, welcher gespeicherte Stand übertragen wird, wie Wiederholungen behandelt werden und was bei einem anderen Serverstand passiert. Ein Verbindungsindikator beantwortet diese Fragen nicht. Die Planung benötigt einen nachvollziehbaren Vertrag zwischen Geräteentwurf, Ausgangswarteschlange, Serveränderung und bestätigtem Ergebnis.
Unser eigenes fiktives Beispiel ist ein Wartungsbericht. Eine Person bearbeitet ihn unterwegs und überträgt den gespeicherten Stand später. Zwei getrennte dateibasierte SQLite-Datenbanken übernehmen im Prüfmodell Geräte- und Serverrolle. Der JavaScript-Baustein läuft in Node.js und demonstriert die Datenentscheidungen. Er ist keine bereits integrierte Android-App und baut auch keine echte Mobilfunkverbindung auf.
Die wichtigste erste Entscheidung lautet, welche Arbeit offline tatsächlich möglich sein soll. Einen eigenen Berichtsentwurf speichern ist etwas anderes als verbindlich verfügbare Termine vergeben oder einen gemeinsamen Bestand abschließend verändern. Unser Beispiel erlaubt den Entwurf und eine spätere geregelte Übertragung. Es verspricht nicht, dass jede fachliche Freigabe unabhängig von einem aktuellen Serverzustand erteilt werden könnte.
Gespeicherten Entwurf und Übertragungsabsicht trennen
Der Gerätebestand enthält den aktuellen Text, seine Revision und die bekannte Serverversion. Eine getrennte Ausgangswarteschlange hält einen unveränderlichen Übertragungsauftrag fest. Dieser Auftrag trägt eine eigene Kennung und den genauen Textstand. Eine spätere Änderung am Entwurf darf nicht still den bereits angelegten Auftrag verändern. Sonst könnte dieselbe Kennung bei verschiedenen Versuchen plötzlich unterschiedliche Inhalte bedeuten.
Im Beispiel heißt der erste Auftrag op-one. Er enthält Revision eins des Berichts und erwartet Serverversion null. Ein erneuter Aufruf der Vormerkfunktion für denselben noch offenen Bericht liefert denselben Auftrag zurück. Es entsteht keine zusätzliche Absicht nur deshalb, weil die Person erneut eine Schaltfläche betätigt. Diese Entscheidung gehört zur fachlichen Wiederholungsregel und ist mehr als eine optische Sperre in der Oberfläche.
Während ein Auftrag offen ist, darf der aktuelle Entwurf weiter geändert werden. Eine zweite automatische Vormerkung für denselben Bericht wird in unserem einfachen Modell zunächst zurückgestellt. Nach Bestätigung kann der neue Stand einen eigenen Auftrag mit der dann bekannten Basisversion erhalten. Diese Begrenzung macht den Ablauf überschaubar. Ein System mit mehreren gleichzeitig offenen Änderungen benötigt ein weitergehendes ausdrückliches Ordnungsmodell.
Dauerhafte Speicherung tatsächlich nachweisen
Eine Variable im Arbeitsspeicher ist keine belastbare Ausgangswarteschlange. Unser Prüfmodell schreibt Entwurf und Auftrag in echte Dateien. Danach wird die Geräteverbindung zur Datenbank geschlossen und neu geöffnet. Die gespeicherten Werte sind weiterhin vorhanden. Dieser konkrete Nachweis ist nützlicher als ein Zustandssymbol, das allein aus einer erfolgreichen Funktionsausführung im Arbeitsspeicher abgeleitet wurde.
Die Vormerkung erfolgt in einer Datenbanktransaktion. Ein bestimmter Bericht und eine bestimmte Revision können durch eine Eindeutigkeitsregel nicht beliebig mehrfach eingetragen werden. Der hier gezeigte synchrone Transaktionshelfer verwendet BEGIN IMMEDIATE und schließt mit Commit oder Rollback. Er wird nicht verschachtelt und enthält keine wartende Netzwerkoperation. Andere Datenbankumgebungen müssen ihre passenden Transaktions- und Konkurrenzregeln bewusst umsetzen.
Auf einem tatsächlichen Mobilgerät gehören Speicherfehler, Prozessende und Wiederherstellung in die Abnahme. Die isolierten SQLite-Dateien beweisen nicht automatisch das Verhalten einer bestimmten Android-Speicherintegration. Sie zeigen die beabsichtigte Datenentscheidung. Eine App verbindet diese mit ihrer eigenen Datenebene und bestätigt gespeicherte Arbeit erst nach der tatsächlichen Persistenz.
Eine verlorene Bestätigung nicht mit einem verlorenen Auftrag verwechseln
Der besonders wichtige Fehlerfall beginnt nach einer erfolgreichen Serveränderung. Der Server hat den Bericht gespeichert, aber das Gerät kann die Bestätigung nicht verarbeiten. Aus Gerätesicht bleibt das Ergebnis unbekannt. Würde es nun einfach einen neuen Auftrag mit neuer Kennung erzeugen, könnte eine nachgelagerte Verarbeitung doppelt ausgelöst werden. Ein erneuter Versuch muss deshalb dieselbe unveränderte Absicht erkennbar mitbringen.
Unser Servermodell speichert zur erfolgreichen Änderung einen Eingangsnachweis mit Auftragskennung, Fingerabdruck des Inhalts und Ergebnisversion. Dieser Nachweis und die Berichtsänderung liegen in derselben Transaktion. Bei einer passenden Wiederholung wird das bekannte Ergebnis zurückgegeben. Eine Wiederverwendung derselben Kennung mit verändertem Inhalt wird dagegen abgewiesen. So wird die Kennung nicht zur pauschalen Erlaubnis für beliebige spätere Änderungen.
Die HTTP-Semantik einer Methode ist von dieser selbst implementierten Wiederholungsregel zu unterscheiden. Ein beliebiger POST wird nicht automatisch durch seinen Namen idempotent. Unser Prüfmodell nutzt direkte Funktionsaufrufe und zeigt die Anwendungsregel unabhängig vom Transport. Eine echte Schnittstelle muss zusätzlich Authentifizierung, konkrete Zugriffsrechte, Antwortzuordnung und ihren vollständigen Fehlervertrag durchsetzen.
Den Serverzustand vor einer Änderung vergleichen
Ein gespeicherter Auftrag erwartet eine bestimmte Basisversion. Der Server vergleicht sie mit seinem aktuellen Bericht. Stimmen sie nicht überein, wird nicht still überschrieben. Der Auftrag erhält einen Versionskonflikt. Im Beispiel bleibt der lokale Text Neue Beobachtung erhalten, während auf dem Server Andere Bearbeitung steht. Beide Fassungen sind wichtige Informationen für die anschließende fachliche Entscheidung.
Ein einfaches Prinzip wie der letzte Schreibzugriff gewinnt kann für bestimmte unkritische Daten genügen. Es ist jedoch keine universelle Konfliktlösung. Zwei Wartungsbeobachtungen könnten verschiedene wichtige Tatsachen enthalten. Eine zeitliche Reihenfolge allein erklärt nicht, welche davon verworfen werden darf. Legen Sie daher fest, ob zusammengeführt, ausdrücklich ausgewählt oder durch eine zuständige Person entschieden wird.
Unsere kleine Implementierung löst den Konflikt nicht automatisch. Sie hält den Auftrag im Zustand conflict und blockiert einen unbemerkten Ersatz durch eine neue Vormerkung. Nach einer ausdrücklich geregelten Klärung müsste ein neuer zulässiger Vorgang entstehen. Der Code enthält diesen Verwaltungsweg bewusst nicht. Die Grenze verhindert, dass ein isoliertes Übertragungsbeispiel als vollständiges fachliches Konfliktsystem missverstanden wird.
Den ausführbaren Datenbaustein lesen
Der folgende Baustein richtet die beiden kleinen Datenmodelle ein, merkt einen konkreten Stand vor und verarbeitet ihn im getrennten Serverbestand. Er wurde mit Node.js 24.22.1 und dem dort vorhandenen SQLite-Modul tatsächlich ausgeführt. Die verwendete Version und der reine Prüfzweck sind wichtig. Der Code ist kein allgemeiner Hintergrunddienst für Browser oder Mobilgeräte und wird nicht automatisch Teil ihrer Datenhaltung.
Die fachliche Berechtigung muss vor applyOperation feststehen. Der Baustein validiert einen begrenzten Eingabevertrag und zeigt anschließend Fingerabdruck, Versionsvergleich und atomare Speicherung. Ein realer HTTP-Empfänger muss zusätzlich seine tatsächlich empfangenen Daten und Antwortschemata kontrollieren. Ein beliebiger Status 200 ohne passend zugeordnetes Ergebnis darf nicht ungeprüft als Bestätigung einer anderen lokalen Revision verwendet werden.
import { DatabaseSync } from 'node:sqlite';
import { createHash } from 'node:crypto';
export function transaction(db, work) {
db.exec('BEGIN IMMEDIATE');
try { const result = work(); db.exec('COMMIT'); return result; }
catch (error) { db.exec('ROLLBACK'); throw error; }
}
export function openClient(path) {
const db = new DatabaseSync(path);
db.exec(`PRAGMA foreign_keys=ON;
CREATE TABLE IF NOT EXISTS drafts(
id TEXT PRIMARY KEY, revision INTEGER NOT NULL,
base_version INTEGER NOT NULL, synced_revision INTEGER,
body TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS outbox(
op_id TEXT PRIMARY KEY, report_id TEXT NOT NULL REFERENCES drafts(id),
revision INTEGER NOT NULL, base_version INTEGER NOT NULL,
body TEXT NOT NULL, state TEXT NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
UNIQUE(report_id, revision));`);
return db;
}
export function openServer(path) {
const db = new DatabaseSync(path);
db.exec(`CREATE TABLE IF NOT EXISTS reports(
id TEXT PRIMARY KEY, version INTEGER NOT NULL, body TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS receipts(
op_id TEXT PRIMARY KEY, fingerprint TEXT NOT NULL,
result_version INTEGER NOT NULL);`);
return db;
}
export function queueCurrent(client, reportId, operationId) {
return transaction(client, () => {
const active = client.prepare("SELECT * FROM outbox WHERE report_id=? AND state IN ('pending','sending','conflict','rejected')").get(reportId);
if (active) return active;
const draft = client.prepare('SELECT * FROM drafts WHERE id=?').get(reportId);
if (!draft || !draft.body.trim()) throw new Error('Usable draft required');
const previous = client.prepare('SELECT * FROM outbox WHERE report_id=? AND revision=?').get(reportId, draft.revision);
if (previous) return previous;
client.prepare('INSERT INTO outbox(op_id,report_id,revision,base_version,body) VALUES(?,?,?,?,?)')
.run(operationId, reportId, draft.revision, draft.base_version, draft.body);
return client.prepare('SELECT * FROM outbox WHERE op_id=?').get(operationId);
});
}
export function applyOperation(server, operation) {
// Authentication and resource permission belong before this helper.
const { op_id, report_id, base_version, body } = operation;
if (typeof op_id !== 'string' || !/^[A-Za-z0-9_-]{1,120}$/u.test(op_id)
|| typeof report_id !== 'string' || !/^[A-Za-z0-9_-]{1,120}$/u.test(report_id) || !Number.isSafeInteger(base_version) || base_version < 0
|| typeof body !== 'string' || !body.trim() || body.length > 4000) {
return { status: 422, code: 'invalid_operation' };
}
const fingerprint = createHash('sha256')
.update(JSON.stringify([report_id, base_version, body])).digest('hex');
return transaction(server, () => {
const known = server.prepare('SELECT * FROM receipts WHERE op_id=?').get(op_id);
if (known) return known.fingerprint === fingerprint
? { status: 200, version: known.result_version, duplicate: true }
: { status: 409, code: 'operation_id_reused' };
const current = server.prepare('SELECT * FROM reports WHERE id=?').get(report_id);
if (!current) return { status: 404, code: 'not_found' };
if (current.version !== base_version) return { status: 409, code: 'version_conflict' };
const version = current.version + 1;
server.prepare('UPDATE reports SET body=?,version=? WHERE id=?')
.run(body, version, report_id);
server.prepare('INSERT INTO receipts VALUES(?,?,?)').run(op_id, fingerprint, version);
return { status: 200, version, duplicate: false };
});
}
export function recordResult(client, operation, result) {
return transaction(client, () => {
if (result.status === 200) {
client.prepare("UPDATE outbox SET state='acknowledged' WHERE op_id=?").run(operation.op_id);
client.prepare('UPDATE drafts SET base_version=?,synced_revision=? WHERE id=?')
.run(result.version, operation.revision, operation.report_id);
} else {
client.prepare('UPDATE outbox SET state=? WHERE op_id=?')
.run(result.status === 409 ? 'conflict' : 'rejected', operation.op_id);
}
});
}
export function attempt(client, server, operationId, loseAcknowledgement = false) {
const operation = client.prepare('SELECT * FROM outbox WHERE op_id=?').get(operationId);
if (!operation || operation.state !== 'pending') throw new Error('Pending operation required');
client.prepare("UPDATE outbox SET state='sending',attempts=attempts+1 WHERE op_id=?").run(operationId);
let result;
try { result = applyOperation(server, operation); }
catch (error) {
client.prepare("UPDATE outbox SET state='pending' WHERE op_id=?").run(operationId);
throw error;
}
if (loseAcknowledgement) {
// Controlled fault point AFTER server commit; preserve the operation ID.
client.prepare("UPDATE outbox SET state='pending' WHERE op_id=?").run(operationId);
return { status: 'acknowledgement_unknown' };
}
recordResult(client, operation, result);
return result;
}
// Run only after the one responsible sender is known to have stopped.
export function recoverInterrupted(client) {
return client.prepare("UPDATE outbox SET state='pending' WHERE state='sending'").run().changes;
}
Aufträge nach Ergebnis unterschiedlich behandeln
Ein bestätigter Auftrag wird acknowledged. Der Gerätebestand erhält die bestätigte Revision und die zugehörige Ergebnisversion. Das ist eine Aussage über genau diesen Stand. Hat die Person inzwischen weitergeschrieben, bleibt der neue Entwurf unverändert und ist weiterhin nicht vollständig synchronisiert. Die Prüfung bestätigt ausdrücklich diesen Unterschied. Eine alte passende Antwort soll nicht zufällig die neue Eingabe als erledigt markieren.
Ein Versionskonflikt bleibt conflict. Eine andere endgültige Ablehnung, etwa eine nicht vorhandene Serverressource, wird im Modell als rejected abgelegt. Auch dabei bleibt der Inhalt erhalten und eine automatische neue Vormerkung wird blockiert. Diese Trennung ermöglicht eine gezielte Klärung. Ein fachlich abgelehnter Auftrag sollte nicht ohne Ende mit derselben unveränderten Voraussetzung in einer engen Wiederholungsschleife laufen.
Eine bekannte Eingangsbestätigung ist außerdem nicht automatisch der aktuelle vollständige Serverstand. Nach der bestätigten Version könnte ein anderes Gerät weitere Änderungen vorgenommen haben. Die nächste eigene Änderung muss deshalb wieder ihre bekannte Basis mit dem aktuellen Stand abgleichen. Ein wiedergegebener Nachweis beantwortet die Frage nach dem alten Auftrag, nicht jede Frage nach späteren Bearbeitungen.
Neustart und unterbrochene Sender bewusst behandeln
Das einfache Modell setzt genau einen zuständigen seriellen Sender voraus. Vor dem Aufruf wird ein Auftrag als sending markiert. Bei einer kontrollierten unbekannten Bestätigung bleibt er anschließend pending. Ein unerwarteter Speicherfehler wird weitergegeben und der Auftrag wieder vormerkbar gehalten. Diese Zustände beschreiben eine begrenzte einzelne Verarbeitung und sind keine verteilte Mehrworker-Sperre.
Nach einem beendeten Sender kann ein dauerhaft gespeicherter sending-Zustand wieder auf pending gesetzt werden. Die Wiederherstellungsfunktion darf deshalb nur aufgerufen werden, wenn der bisherige zuständige Sender tatsächlich nicht mehr läuft. Würden mehrere unabhängige Worker einander unkontrolliert zurücksetzen, wäre diese Annahme verletzt. Ein größeres System benötigt passende Besitz-, Lease- oder Koordinationsregeln und deren eigene Konkurrenzprüfung.
Die Tests schließen und öffnen die echte Gerätedatenbank mit einem solchen unterbrochenen Zustand. Die Wiederherstellung behält dieselbe Auftragskennung und ist bei erneuter Ausführung ohne weitere Wirkung. Anschließend kann der Auftrag verarbeitet werden. Das ist ein konkreter Persistenz- und Wiederanlaufnachweis. Er behauptet keine bereits getestete Betriebssystemplanung oder automatische Zustellung unter allen Mobilbedingungen.
Wiederholungen mit Kapazität und Betrieb abstimmen
Eine Verbindung kann wechselhaft sein und der Server kann vorübergehend nicht bereitstehen. Eine sinnvolle Wiederholungsplanung benötigt deshalb Abstände, Grenzen und verständliche Rückmeldungen. Eine sofortige unendliche Schleife belastet Gerät und Gegenstelle, ohne das zugrunde liegende Problem zwangsläufig zu lösen. Unser Code zählt Versuche, implementiert aber bewusst keinen vollständigen Scheduler. Diese Zuständigkeit bleibt im realen Anwendungsaufbau gesondert sichtbar.
Für Android bietet WorkManager Bausteine für beständige Hintergrundarbeit, Bedingungen und Wiederholungsstrategien. Die geprüfte Dokumentation beschreibt unter anderem Verbindungsbedingungen und Backoff. Eine konkrete App muss diese mit ihrem Datenvertrag verbinden. Ein geplanter Hintergrundauftrag ist nicht selbst der Nachweis, dass der Server den gewünschten Inhalt schon angenommen hat. Die endgültige Oberfläche folgt weiterhin dem tatsächlich verarbeiteten Ergebnis.
Auch die Aufbewahrung erfolgreicher Eingangsnachweise braucht eine abgestimmte Regel. Wie lange kann ein Gerät noch mit einer alten unbekannten Bestätigung zurückkommen? Was geschieht, wenn ein Nachweis nicht mehr vorhanden ist? Unser kleines Modell behält seine Nachweise. Eine produktive Begrenzung darf diesen Zusammenhang nicht unbemerkt zerstören und muss mit dem Wiederholungs- und Klärungsweg gemeinsam geplant werden.
Android Developers: Work requests
Den Konfliktweg für Menschen gestalten
Eine Person benötigt keine rohe Datenbankfehlermeldung, um einen Konflikt zu verstehen. Die Oberfläche kann den eigenen gespeicherten Stand, den anderen Stand und die offene Entscheidung nachvollziehbar benennen. Welche Details sie zeigen darf, hängt von der tatsächlichen Berechtigung ab. Unser fiktives Modell zeigt die beiden eigenen kurzen Beispieltexte, ohne daraus einen allgemeinen Umgang mit vertraulichen Fremddaten abzuleiten.
Eine Auflösung braucht eine klare Handlung. Das kann das ausdrückliche Beibehalten einer Fassung, eine geprüfte Zusammenführung oder eine Übergabe an eine zuständige Person sein. Der dabei entstehende Vorgang muss wieder eine passende Basis und einen nachvollziehbaren Inhalt besitzen. Ein stilles Zurücksetzen der Versionsnummer würde den sichtbaren Konflikt nur verdecken. Die fachliche Entscheidung darf nicht durch einen zufälligen technischen Standardwert ersetzt werden.
Auch ohne Konflikt muss der Status verständlich bleiben: auf Gerät gespeichert, zur Übertragung vorgemerkt, unterwegs oder bestätigt. Die App darf weiterhin bearbeitbare neue Änderungen neben einem älteren bestätigten Stand zeigen. Genau diese Unterscheidung verbindet Datenmodell und Oberfläche. Das Speicher- und Übertragungsmodell liefert die Tatsachen, während die Gestaltung daraus eine sinnvolle nächste Aufgabe ableitet.
Die 69 tatsächlich ausgeführten Fälle einordnen
Die Prüfungen verwenden echte getrennte SQLite-Dateien. Sie bestätigen Speicherung und Wiederöffnung, eine unveränderte Vormerkung, eine kontrolliert verlorene Bestätigung nach Servercommit und die passende Wiederholung. Der Server bleibt dabei auf Version eins und führt keine zweite Änderung aus. Eine veränderte Nutzlast mit derselben Kennung wird abgewiesen. Der erfolgreiche Nachweis überlebt auch eine Wiederöffnung des Serverbestands.
Weitere Fälle betreffen einen veränderten Serverstand, einen Rollback bei kollidierendem Nachweis, ungültige Werte, einen fehlenden Servergegenstand und einen unterbrochenen Sender. Eine ältere Bestätigung lässt einen neueren Geräteentwurf unverändert. Danach kann der neue Stand mit einer neuen passenden Basis übertragen werden. Insgesamt werden 69 konkrete Prüfungen ausgeführt. Es handelt sich nicht um eine erfundene Zustellquote oder eine Produktionskennzahl.
Der Fehler nach Commit wird an einer kontrollierten Stelle zwischen Serververarbeitung und Bestätigungsübernahme ausgelöst. Es wird keine echte Funkstrecke getrennt und keine Mehrworker-Last erzeugt. Diese Grenze ist für die Aussage wichtig. Das Beispiel prüft den Datenvertrag und seine Wiederholungsfolgen. Eine echte App ergänzt Netzwerk-, Betriebssystem-, Berechtigungs- und Konkurrenztests passend zu ihrer tatsächlichen Umsetzung.

Eine Abnahme mit Störungen statt nur mit Erfolg planen
Beginnen Sie mit einer normalen Aufgabe: Bericht erstellen, ohne Verbindung speichern und nach Neustart wiederfinden. Danach wird der vorgemerkte Stand verarbeitet. Als nächster Fall wird die Bestätigung nach einer erfolgreichen Gegenstellenänderung nicht übernommen. Der erneute Versuch muss denselben Auftrag verwenden. Diese Reihenfolge zeigt, ob die Anwendung einen unbekannten Ausgang sachgerecht behandelt oder nur einen reibungslosen ersten Versuch kennt.
Ein weiterer Fall lässt einen anderen Akteur den Serverstand verändern, bevor der gespeicherte Auftrag verarbeitet wird. Der erwartete Konflikt darf weder den lokalen Text noch den anderen Stand unbemerkt zerstören. Anschließend wird der vorgesehene Klärungsweg mit einer fachlich zuständigen Person geprüft. Ein bloßer roter Fehlerbereich ohne Handlung würde den Datenverlust zwar vermeiden, die eigentliche Arbeit aber weiterhin blockieren.
Prüfen Sie außerdem Speicherfehler, abgelaufene Anmeldung und die genaue Zuordnung von Antworten. Eine Anwendung darf nach einer fremden oder veralteten Antwort nicht versehentlich den falschen Entwurf als bestätigt markieren. Die 69 isolierten Fälle liefern einen klaren Kern, ersetzen jedoch nicht diese äußeren Wege. Eine gute Abnahme beschreibt deshalb erwartetes Verhalten und tatsächlich geprüfte Ebene jeweils gemeinsam.
Den Umfang und die Verantwortlichkeiten festhalten
Offlinearbeit betrifft Produkt, Datenmodell und Betrieb zugleich. Fachpersonen entscheiden, welche Arbeit ohne aktuellen Serverstand zulässig ist. Entwicklung legt verlässliche Speicherung, Auftragsidentität und Versionsprüfung fest. Gestaltung erklärt Zustand und nächste Handlung. Betrieb plant Wiederholung, Grenzen und Untersuchung fehlgeschlagener Vorgänge. Keine dieser Aufgaben wird durch ein einzelnes Verbindungssymbol vollständig übernommen.
Für die Übergabe dokumentieren wir die beteiligten Datenbestände, den Auftragstyp, die Lebensdauer der Kennung und den Konfliktweg. Das einfache Modell erlaubt einen offenen Auftrag pro Bericht und einen seriellen Sender. Diese Annahmen bleiben sichtbar. Wenn ein späterer Ausbau mehrere Geräte oder parallele Aufträge intensiver verbindet, werden die Regeln gezielt erweitert statt nur zusätzliche Schleifen um denselben kleinen Beispielcode zu legen.
Das Ergebnis ist eine nachvollziehbare Vereinbarung darüber, was gespeichert, vorgemerkt und bestätigt bedeutet. Menschen können weiterarbeiten, während unklare Ausgänge und andere Bearbeitungen kontrolliert behandelt werden. Der kleine echte SQLite-Versuch zeigt dafür einen überprüften Kern. Die fertige Anwendung verbindet ihn mit ihren tatsächlichen Zugriffen, Geräten und Rückmeldungen und belegt diese Verbindung mit passenden Integrationstests.
Auftragsidentität nicht mit gleichem Text verwechseln
Zwei verschiedene Auftragskennungen mit identischem Text sind im Beispiel zwei verschiedene Absichten. Der Server erkennt bekannte Aufträge und vergleicht deren eingefrorenen Inhalt. Er führt keine allgemeine Suche nach ähnlichen Berichten durch. Das ist wichtig, weil zwei fachlich unterschiedliche Beobachtungen zufällig dieselbe kurze Formulierung besitzen können. Eine pauschale Textgleichheit wäre deshalb kein zuverlässiger Beleg dafür, dass dieselbe Arbeit bereits erledigt wurde.
Umgekehrt muss eine Anwendung nicht bei jedem erneuten Speichern unveränderter Eingaben zwangsläufig eine neue fachliche Revision erzeugen. Die zuständige Datenebene legt fest, wann tatsächlich eine Änderung entstanden ist. Unser kleiner Baustein erhält die Revision als bereits vereinbarten Zustand. Er zeigt, wie genau dieser Stand eingefroren und bestätigt wird. Die Gestaltung einer Speichern-Schaltfläche ersetzt diese vorgelagerte Änderungsentscheidung nicht.
Zur Übergabe unterscheiden wir daher Berichtskennung, Revision und Auftragskennung. Die Berichtskennung bezeichnet den Gegenstand. Die Revision bezeichnet seinen konkreten Geräteinhalt. Die Auftragskennung bezeichnet die unveränderliche Übertragungsabsicht. Nach einer unklaren Antwort bleibt diese Absicht dieselbe. Nach einer fachlich geklärten neuen Änderung kann eine neue entstehen. Diese drei verständlichen Begriffe helfen, Wiederholung, Neubearbeitung und Konflikt nicht versehentlich als denselben Vorgang zu behandeln.
Wichtige Datenentscheidungen
| Situation | Regel im Beispiel |
|---|---|
| Keine Verbindung | Entwurf und Vormerkung dauerhaft erhalten |
| Bestätigung fehlt nach Commit | Gleiche Kennung und unveränderten Auftrag wiederholen |
| Gleiche Kennung, anderer Inhalt | Ablehnen |
| Andere Serverversion | Konflikt erhalten, nicht still überschreiben |
| Neuer Text nach alter Bestätigung | Nur die alte Revision als bestätigt markieren |
| Beendeter einzelner Sender | Offene sending-Aufträge kontrolliert wieder vormerken |
Checkliste für die Synchronisierung
- Offline zulässige Aufgaben und offene fachliche Grenzen festlegen.
- Entwurf und unveränderliche Übertragungsabsicht trennen.
- Kennung bei unbekanntem Ausgang erhalten.
- Serveränderung und passenden Eingangsnachweis atomar speichern.
- Versionskonflikte ohne stillen Datenverlust behandeln.
- Ältere Bestätigungen von neuen Entwürfen unterscheiden.
- Senderbesitz, Wiederanlauf, Backoff und Nachweisaufbewahrung regeln.
- Datenvertrag und echte Transport-/Geräteintegration getrennt prüfen.
Quellen und Prüfstand
Primärquellen am 09.11.2026 geprüft. Eigener fiktiver Wartungsbericht, tatsächlich ausgeführtes Node.js-24.22.1-/SQLite-Modell mit 69 Fällen und echten Dateien. Die Bestätigung wird kontrolliert nach Commit als unbekannt behandelt. Kein echter Funkstrecken-, Android- oder Mehrworker-Lastnachweis.








