feat(nextcloud-status): Meldung in Tessera, Anleitung und Changelog
- Endpunkt für letzte Übergänge der abonnierten Clouds, globaler Melder im Portalrahmen (Desktop: Windows-Benachrichtigung) - Anleitung für Anwender und Administration, Changelog Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,20 @@ export interface AlertCheckedRow {
|
||||
alertState: string;
|
||||
}
|
||||
|
||||
/** Eine Meldung fuer die Anzeige in Tessera (D-K7). */
|
||||
export interface RecentAlert {
|
||||
instanceId: string;
|
||||
customerName: string;
|
||||
baseUrl: string;
|
||||
kind: 'down' | 'up';
|
||||
/** Rote Grundkennung (z. B. 'unreachable'); nur bei `down`. */
|
||||
reason: string | null;
|
||||
changedAt: string;
|
||||
}
|
||||
|
||||
/** Zeitraum, in dem ein Uebergang noch als Meldung in Tessera erscheint. */
|
||||
export const RECENT_ALERT_WINDOW_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
export interface AlertEvaluation {
|
||||
kind: AlertTransition;
|
||||
/** Der laufende Versand (nur fuer Tests zum Abwarten; der Pruefpfad wartet nie darauf). */
|
||||
@@ -108,6 +122,68 @@ export class NextcloudAlertService {
|
||||
return new Set(rows.map((r) => r.instanceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Letzte Uebergaenge der Clouds, fuer die DER AUFRUFER die Glocke eingeschaltet
|
||||
* hat (quick-261002-kxc, L-04, D-K7, T-kxc-02): je Cloud der juengste
|
||||
* Uebergang der letzten 24 Stunden, sofern er NACH dem Einschalten der Glocke
|
||||
* lag. Der Browser zeigt daraus je (Cloud, Zeitpunkt) hoechstens einmal eine
|
||||
* Meldung. Nur skalare Felder, die die Modulseite ohnehin zeigt.
|
||||
*/
|
||||
async listRecentAlerts(
|
||||
tenantId: string,
|
||||
userId: string,
|
||||
now: Date = new Date(),
|
||||
): Promise<{ alerts: RecentAlert[] }> {
|
||||
const tenantPrisma = forTenant(this.prisma, tenantId, userId);
|
||||
const subs: { instanceId: string; createdAt: Date }[] =
|
||||
await tenantPrisma.nextcloudAlertSubscription.findMany({
|
||||
where: { tenantId, userId },
|
||||
select: { instanceId: true, createdAt: true },
|
||||
});
|
||||
if (subs.length === 0) return { alerts: [] };
|
||||
|
||||
const since = new Date(now.getTime() - RECENT_ALERT_WINDOW_MS);
|
||||
const instances: {
|
||||
id: string;
|
||||
customerName: string;
|
||||
baseUrl: string;
|
||||
alertState: string;
|
||||
alertReason: string | null;
|
||||
alertChangedAt: Date | null;
|
||||
}[] = await tenantPrisma.nextcloudInstance.findMany({
|
||||
where: {
|
||||
tenantId,
|
||||
id: { in: subs.map((s) => s.instanceId) },
|
||||
alertChangedAt: { gte: since },
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
customerName: true,
|
||||
baseUrl: true,
|
||||
alertState: true,
|
||||
alertReason: true,
|
||||
alertChangedAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
const subscribedAt = new Map(subs.map((s) => [s.instanceId, s.createdAt]));
|
||||
const alerts: RecentAlert[] = [];
|
||||
for (const i of instances) {
|
||||
const subscribed = subscribedAt.get(i.id);
|
||||
if (!i.alertChangedAt || !subscribed || i.alertChangedAt < subscribed) continue;
|
||||
alerts.push({
|
||||
instanceId: i.id,
|
||||
customerName: i.customerName,
|
||||
baseUrl: i.baseUrl,
|
||||
kind: i.alertState === 'red' ? 'down' : 'up',
|
||||
reason: i.alertState === 'red' ? i.alertReason : null,
|
||||
changedAt: i.alertChangedAt.toISOString(),
|
||||
});
|
||||
}
|
||||
alerts.sort((a, b) => a.changedAt.localeCompare(b.changedAt));
|
||||
return { alerts };
|
||||
}
|
||||
|
||||
/**
|
||||
* Entscheidet nach einer Pruefung, ob eine Meldung faellig ist, beansprucht
|
||||
* den Uebergang und startet den Versand im Hintergrund. Wartet nur auf den
|
||||
|
||||
Reference in New Issue
Block a user