Benachrichtigungen wecken das Telefon wieder: Urgency je Art
Diene hat gemeldet: "Die Benachrichtigungen werden nicht angezeigt,
wenn neue Nachrichten reinkommen. Erst, wenn man die App oeffnet."
Alles Messbare war gruen: Der Service Worker zeigt die Meldung bei
geschlossener App (pruef-push-zu, 13 Pruefungen), jede Anmeldung im
Haus stand auf fehler = 0, der Push-Dienst quittierte mit 201. Nur
den Kopf auf der Leitung hat nie jemand gemessen:
Urgency: normal
Beide Dienste behandeln das ausdruecklich als "darf warten".
Android/FCM haelt solche Meldungen zurueck, solange das Telefon
doest, und stellt sie zu, wenn es aufwacht -- typischerweise beim
Entsperren oder Oeffnen der App. Apple/APNs nennt es "verzoegert,
gebuendelt oder gedrosselt". Das ist Dienes Satz, Wort fuer Wort,
und es stand als Vorgabe im eigenen Quelltext.
zuletzt_ok konnte das nie zeigen: Es beweist, dass der DIENST
angenommen hat, nicht dass das GERAET etwas angezeigt hat.
Bis hierher hing die Dringlichkeit an der Ruheregel (dringend =
regel === "nie"), mit der Begruendung, "darf das nachts stoeren?"
und "darf das warten?" haetten dieselbe Antwort. Haben sie nicht:
Ein Chat um 3 Uhr soll schweigen, um 14 Uhr aber nicht vierzig
Minuten liegen bleiben. Jetzt zwei Felder -- in DERSELBEN Zeile
derselben Artenliste, damit sie nicht auseinanderlaufen koennen.
10 von 19 Arten sind eilig (Anruf, Chat, Erwaehnung, Support, Hilfe,
Termin, Wecker, zweimal Live, Probe). Die anderen neun duerfen
warten -- waere alles eilig, waere nichts mehr eilig.
DIE FALLE BEIM BEHEBEN: dringend steuerte auch die Haltbarkeit
(TTL 150). Ein einfach auf "dringend" gestellter Chat waere nach
150 s verfallen -- wer sein Telefon drei Minuten aus hat, haette die
Nachricht GAR nicht mehr bekommen. Aus "zu spaet" waere "nie"
geworden. Deshalb sind eilig und kurzlebig getrennt; kurzlebig
bleibt genau beim Anruf und der Probe.
Der alte Name kracht jetzt, statt still "normal" zu liefern.
pruef-push-eilig.mjs (neu, 13 Pruefungen): die Entscheidung je Art
unabhaengig notiert statt aus der Artenliste abgelesen, jede Art
muss eine Entscheidung haben, und der Kopf wird durch
benachrichtige() hindurch an einem nachgebauten Push-Dienst
gemessen. Gegenprobe gelaufen: ohne das Feld meldet sie
"chat_nachricht geht mit Urgency: normal hinaus", 4 Fehler.
Die Uhr ist dort eine Eingabe, keine Annahme -- die Zeitzone wird so
gewaehlt, dass der Lauf immer auf 12 Uhr faellt, sonst waere die
Pruefung nachts rot ohne Befund.
pruef-anruf-klingelt 25 -> 26. Dabei aufgefallen: Eine ihrer
Pruefungen war gruen, obwohl die Zeile aus dem Code verschwunden war
-- sie stand nur noch in einem Kommentar, der die alte Fassung
zitiert. Quelltextpruefungen lesen dort jetzt ohne Kommentare.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+69
-19
@@ -113,19 +113,19 @@ const jetzt = () => new Date().toISOString();
|
||||
export const ARTEN = [
|
||||
{ schluessel: "aufgabe_faellig", name: "Aufgabe wird morgen fällig", vorgabe: true },
|
||||
{ schluessel: "aufgabe_ueberfaellig", name: "Aufgabe ist überfällig", vorgabe: true },
|
||||
{ schluessel: "termin_gleich", name: "Termin in einer Stunde", vorgabe: true },
|
||||
{ schluessel: "termin_gleich", eilig: true, name: "Termin in einer Stunde", vorgabe: true },
|
||||
/* DER WECKER (07.09.2026). Bewusst eine EIGENE Art neben
|
||||
"termin_gleich": Die eine ist eine Vorgabe des Hauses fuer jeden
|
||||
Termin, der andere ist eine Entscheidung DIESER Person fuer DIESEN
|
||||
Termin. Wer die feste Stunden-Erinnerung abschaltet, will damit
|
||||
nicht seine selbst gesetzten Wecker verlieren. */
|
||||
{ schluessel: "termin_wecker", name: "Selbst gesetzter Wecker", vorgabe: true },
|
||||
{ schluessel: "termin_wecker", eilig: true, name: "Selbst gesetzter Wecker", vorgabe: true },
|
||||
{ schluessel: "protokoll_fehlt", name: "Gespräch ohne Protokoll", vorgabe: true },
|
||||
{ schluessel: "followup", name: "Follow-up in der Pipeline fällig", vorgabe: true },
|
||||
/* Chat (06.09.2026). Steht bewusst VOR der Probe: Es ist die Art,
|
||||
die am haeufigsten kommt, und wer die Liste ueberfliegt, sucht
|
||||
zuerst sie. */
|
||||
{ schluessel: "chat_nachricht", name: "Neue Nachricht im Chat", vorgabe: true },
|
||||
{ schluessel: "chat_nachricht", eilig: true, name: "Neue Nachricht im Chat", vorgabe: true },
|
||||
/* ---- ANGESPROCHEN WERDEN IST EINE EIGENE ART (20.09.2026) ------
|
||||
|
||||
Filipe: "ich will das man die leute mit @ markieren kann im chat."
|
||||
@@ -144,7 +144,7 @@ export const ARTEN = [
|
||||
KEINE Ausnahme von der Ruhezeit: Ein Anruf wartet auf eine
|
||||
Antwort, ein "@Anna" nicht. Wer um halb vier angesprochen wird,
|
||||
liest es um sieben -- das reicht. */
|
||||
{ schluessel: "chat_erwaehnung", name: "Jemand erwähnt dich im Chat (@)", vorgabe: true },
|
||||
{ schluessel: "chat_erwaehnung", eilig: true, name: "Jemand erwähnt dich im Chat (@)", vorgabe: true },
|
||||
|
||||
/* ---- BEWERBUNGEN (23.09.2026) -----------------------------------
|
||||
|
||||
@@ -189,7 +189,7 @@ export const ARTEN = [
|
||||
|
||||
NICHT DRINGEND: Ein kaputter Knopf weckt niemanden um drei Uhr
|
||||
nachts; die Ruhezeit gilt. */
|
||||
{ schluessel: "support",
|
||||
{ schluessel: "support", eilig: true,
|
||||
name: "Support: neue Meldung oder Antwort darauf", vorgabe: true },
|
||||
|
||||
/* ---- MANAGER-ZIELE (02.10.2026) ---------------------------------
|
||||
@@ -224,7 +224,7 @@ export const ARTEN = [
|
||||
Eine eigene Art und nicht "termin_gleich": Das eine ist ein
|
||||
Kalendereintrag, das andere ein Stream, der JETZT laeuft. Wer das
|
||||
eine stumm stellt, meint selten das andere. */
|
||||
{ schluessel: "dogfather_live", name: "DogFather ist live", vorgabe: true,
|
||||
{ schluessel: "dogfather_live", eilig: true, name: "DogFather ist live", vorgabe: true,
|
||||
/* „spaet", nicht „immer": Ein Stream, der um 22:05 anfaengt, ist um
|
||||
22:05 interessant. Mit der alten Regel waere er stumm geblieben,
|
||||
und die Meldung, die Filipe ausdruecklich bestellt hat („die
|
||||
@@ -257,7 +257,7 @@ export const ARTEN = [
|
||||
|
||||
`ruhe: "spaet"` aus demselben Grund wie oben: Eine Reaction um
|
||||
22:30 ist der Normalfall, keine Ausnahme. */
|
||||
{ schluessel: "reaktion_live",
|
||||
{ schluessel: "reaktion_live", eilig: true,
|
||||
name: "Die Reaction geht auf Sendung", vorgabe: true, ruhe: "spaet" },
|
||||
/* ---- ANRUFE SIND EINE EIGENE ART (18.09.2026) ------------------
|
||||
|
||||
@@ -283,7 +283,7 @@ export const ARTEN = [
|
||||
ist kein Telefon. Wer nachts nicht gestoert werden will, schaltet
|
||||
jetzt diese Art ab -- eine Entscheidung, die man selbst trifft,
|
||||
statt einer Regel, die man nicht kennt. */
|
||||
{ schluessel: "anruf", name: "Jemand ruft an", vorgabe: true, ruhe: "nie" },
|
||||
{ schluessel: "anruf", eilig: true, name: "Jemand ruft an", vorgabe: true, ruhe: "nie" },
|
||||
/* DER TAGESRUF (08.09.2026, screen10). Filipe: "eine taetige meldung
|
||||
einmal am tag zu aktivieren wenn noch aufgaben auf sind."
|
||||
|
||||
@@ -323,10 +323,10 @@ export const ARTEN = [
|
||||
|
||||
IM TEXT STEHT NIE, WORUM ES GEHT. Eine Benachrichtigung erscheint
|
||||
auf einem Sperrbildschirm, den auch andere sehen. */
|
||||
{ schluessel: "hilfe", name: "Vertrauliche Meldung: neu oder beantwortet", vorgabe: true },
|
||||
{ schluessel: "hilfe", eilig: true, name: "Vertrauliche Meldung: neu oder beantwortet", vorgabe: true },
|
||||
/* Die Probe beantwortet „kommt ueberhaupt etwas an?" -- und die
|
||||
stellt man sich auch um 23 Uhr. */
|
||||
{ schluessel: "test", name: "Probe-Benachrichtigung", vorgabe: true, ruhe: "nie" },
|
||||
{ schluessel: "test", eilig: true, name: "Probe-Benachrichtigung", vorgabe: true, ruhe: "nie" },
|
||||
];
|
||||
const ARTEN_SCHLUESSEL = new Set(ARTEN.map((a) => a.schluessel));
|
||||
|
||||
@@ -382,6 +382,49 @@ export function ruheRegel(art) {
|
||||
return ARTEN.find((a) => a.schluessel === art)?.ruhe || "immer";
|
||||
}
|
||||
|
||||
/** Ist diese Art EILIG -- also wertlos, wenn sie zu spaet kommt?
|
||||
*
|
||||
* WARUM DAS EINE EIGENE FRAGE IST (03.10.2026, nach Dienes Meldung).
|
||||
*
|
||||
* Diene hat gemeldet: "Die Benachrichtigungen werden nicht angezeigt,
|
||||
* wenn neue Nachrichten reinkommen. Erst, wenn man die App oeffnet."
|
||||
* Das war kein Fehler an ihrem Geraet und keiner am Service Worker --
|
||||
* es war der Kopf `Urgency`, den wir mitschicken.
|
||||
*
|
||||
* Beide Push-Dienste behandeln "normal" ausdruecklich als "darf
|
||||
* warten": Android/FCM haelt solche Meldungen zurueck, solange das
|
||||
* Telefon doest, und stellt sie zu, wenn es aufwacht -- typischerweise,
|
||||
* wenn jemand das Geraet entsperrt oder die App oeffnet. Apple/APNs
|
||||
* nennt es "verzoegert, gebuendelt oder gedrosselt". Beschrieben ist
|
||||
* damit genau Dienes Satz, Wort fuer Wort.
|
||||
*
|
||||
* Bis hierher hing die Dringlichkeit an der RUHEREGEL:
|
||||
*
|
||||
* const dringend = regel === "nie";
|
||||
*
|
||||
* Daneben stand die Begruendung, eine zweite Bedingung sei die, "die
|
||||
* beim naechsten Nachschaerfen auseinanderlaeuft". Die Vorhersage war
|
||||
* richtig, nur in die andere Richtung: Die zwei Fragen haben eben
|
||||
* NICHT dieselbe Antwort.
|
||||
*
|
||||
* "Darf das nachts stoeren?" -> Chat: nein.
|
||||
* "Darf das warten?" -> Chat: auch nein.
|
||||
*
|
||||
* Eine Nachricht um drei Uhr nachts soll schweigen -- um zwei Uhr
|
||||
* nachmittags aber nicht vierzig Minuten liegen bleiben. Deshalb zwei
|
||||
* Felder, aber in DERSELBEN Liste: auseinanderlaufen koennen sie nur,
|
||||
* wenn sie an zwei Orten stehen.
|
||||
*
|
||||
* MASSSTAB: eilig ist, was durch Warten WERTLOS wird -- ein Anruf, ein
|
||||
* Wecker, eine Nachricht, auf die jemand wartet, ein "wir sind live".
|
||||
* Nicht eilig ist, was auch spaeter noch stimmt -- eine Aufgabe, die
|
||||
* morgen faellig ist, der Tagesruf, eine Bewerbung. Waere alles eilig,
|
||||
* waere nichts mehr eilig: Die Geraete duerfen uns die Dringlichkeit
|
||||
* glauben, sonst drosseln sie uns -- und der Akku zahlt es mit. */
|
||||
export function eiligRegel(art) {
|
||||
return ARTEN.find((a) => a.schluessel === art)?.eilig === true;
|
||||
}
|
||||
|
||||
/** Ist gerade Ruhezeit -- fuer diese Regel?
|
||||
*
|
||||
* `regel` steht hinten und hat eine Vorgabe, damit vorhandene
|
||||
@@ -598,7 +641,21 @@ export async function benachrichtige(personId, art, { titel, text, ziel, merkmal
|
||||
schlafendes Geraet dafuer aufwacht. Das gilt fuer den Anruf und
|
||||
die Probe -- nicht fuer eine Einladung: Die soll ankommen, wenn
|
||||
das Geraet ohnehin wach wird, und keinen Akku dafuer verbrennen. */
|
||||
const dringend = regel === "nie";
|
||||
const eilig = eiligRegel(art);
|
||||
/* KURZLEBIG IST NICHT DASSELBE WIE EILIG -- und das Zusammenlegen
|
||||
waere hier der teure Fehler gewesen (03.10.2026).
|
||||
|
||||
Bis heute steuerte EIN Schalter beides: `dringend` hat das Geraet
|
||||
geweckt UND die Haltbarkeit auf 150 Sekunden gesetzt. Haette ich
|
||||
den Chat einfach auf `dringend` gestellt, waere aus "kommt vierzig
|
||||
Minuten zu spaet" ein "kommt gar nicht mehr" geworden: Wer sein
|
||||
Telefon drei Minuten aus hat, haette die Nachricht dann verloren.
|
||||
Schlimmer als der Fehler, den ich beheben wollte.
|
||||
|
||||
Kurz haltbar bleibt deshalb genau das, was von selbst vorbei ist
|
||||
-- der Anruf, der 120 Sekunden klingelt, und die Probe, bei der
|
||||
jemand davorsteht. Das ist unveraendert `ruhe: "nie"`. */
|
||||
const kurzlebig = regel === "nie";
|
||||
|
||||
/* Schon einmal geschickt? */
|
||||
if (merkmal) {
|
||||
@@ -633,14 +690,7 @@ export async function benachrichtige(personId, art, { titel, text, ziel, merkmal
|
||||
|
||||
let raus = 0;
|
||||
for (const a of anmeldungen) {
|
||||
/* EIN ANRUF IST DRINGEND, ALLES ANDERE NICHT (19.09.2026).
|
||||
|
||||
`dringend` ist hier dasselbe `art === "anruf"`, das zwanzig
|
||||
Zeilen weiter oben schon ueber die Ruhezeit entscheidet -- die
|
||||
Frage „darf das nachts stoeren?" und „darf das warten?" haben
|
||||
dieselbe Antwort. Eine zweite Bedingung waere die, die beim
|
||||
naechsten Nachschaerfen auseinanderlaeuft. */
|
||||
const e = await schicken(a, inhalt, paar, ABSENDER, { dringend });
|
||||
const e = await schicken(a, inhalt, paar, ABSENDER, { eilig, kurzlebig });
|
||||
if (e.ok) {
|
||||
raus++;
|
||||
db().prepare("UPDATE push_anmeldungen SET zuletzt_ok = ?, fehler = 0 WHERE endpunkt = ?")
|
||||
|
||||
Reference in New Issue
Block a user