From 75053bbbb1f4ec917739c44cbc45fa1c17fd3dd5 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Thu, 19 Mar 2026 13:26:52 -0700 Subject: [PATCH] Create health check framework --- .../RelaySettingsActionItems.svelte | 140 ------------------ ...svelte => RelaySettingsHealthCheck.svelte} | 25 ++-- .../RelaySettingsHealthChecks.svelte | 43 ++++++ src/app/util/health.ts | 107 +++++++++++++ src/routes/settings/relays/+page.svelte | 4 +- 5 files changed, 164 insertions(+), 155 deletions(-) delete mode 100644 src/app/components/RelaySettingsActionItems.svelte rename src/app/components/{RelaySettingsActionItem.svelte => RelaySettingsHealthCheck.svelte} (52%) create mode 100644 src/app/components/RelaySettingsHealthChecks.svelte create mode 100644 src/app/util/health.ts diff --git a/src/app/components/RelaySettingsActionItems.svelte b/src/app/components/RelaySettingsActionItems.svelte deleted file mode 100644 index cc2f7f00..00000000 --- a/src/app/components/RelaySettingsActionItems.svelte +++ /dev/null @@ -1,140 +0,0 @@ - - -
-
- - - Health Check - - - - {$actionItems.length} Issue{$actionItems.length === 1 ? "" : "s"} Detected - -
-

- {PLATFORM_NAME} actively checks your connection to the network in the background to discover relays - that are offline, that you don't have access to, or are otherwise causing trouble. -

- {#each $actionItems as actionItem} - - {/each} - {#if $actionItems.length > 0} - - {/if} -
diff --git a/src/app/components/RelaySettingsActionItem.svelte b/src/app/components/RelaySettingsHealthCheck.svelte similarity index 52% rename from src/app/components/RelaySettingsActionItem.svelte rename to src/app/components/RelaySettingsHealthCheck.svelte index 260ab870..f562b226 100644 --- a/src/app/components/RelaySettingsActionItem.svelte +++ b/src/app/components/RelaySettingsHealthCheck.svelte @@ -1,27 +1,26 @@ - -
- {title} -

{subtitle}

+ {healthCheck.title} +

{healthCheck.description}

diff --git a/src/app/components/RelaySettingsHealthChecks.svelte b/src/app/components/RelaySettingsHealthChecks.svelte new file mode 100644 index 00000000..aca78b0e --- /dev/null +++ b/src/app/components/RelaySettingsHealthChecks.svelte @@ -0,0 +1,43 @@ + + +
+
+ + + Health Check + + + + {$pendingHealthChecks.length} Issue{$pendingHealthChecks.length === 1 ? "" : "s"} Detected + +
+

+ {PLATFORM_NAME} actively checks your connection to the network in the background to discover relays + that are offline, that you don't have access to, or are otherwise causing trouble. +

+ {#each $pendingHealthChecks as healthCheck} + + {/each} + {#if $pendingHealthChecks.length > 0} + + {/if} +
diff --git a/src/app/util/health.ts b/src/app/util/health.ts new file mode 100644 index 00000000..f9f6f61a --- /dev/null +++ b/src/app/util/health.ts @@ -0,0 +1,107 @@ +import {derived, get} from "svelte/store" +import {not, ifLet, sample} from "@welshman/lib" +import {getRelaysFromList, RelayMode} from "@welshman/util" +import { + getRelay, + setWriteRelays, + setReadRelays, + setSearchRelays, + setMessagingRelays, + userRelayList, + userSearchRelayList, + userMessagingRelayList, +} from "@welshman/app" +import {hasNip50, DEFAULT_RELAYS, DEFAULT_MESSAGING_RELAYS} from "@app/core/state" + +export type HealthCheckContext = { + readRelays: string[] + writeRelays: string[] + messagingRelays: string[] + searchRelays: string[] +} + +export type HealthCheck = { + title: string + description: string + action: string + isPending: (context: HealthCheckContext) => boolean + apply: (context: HealthCheckContext) => unknown +} + +export const healthCheckContext = derived( + [userRelayList, userSearchRelayList, userMessagingRelayList], + ([$userRelayList, $userSearchRelayList, $userMessagingRelayList]) => { + return { + readRelays: getRelaysFromList($userRelayList, RelayMode.Read), + writeRelays: getRelaysFromList($userRelayList, RelayMode.Write), + searchRelays: getRelaysFromList($userSearchRelayList), + messagingRelays: getRelaysFromList($userMessagingRelayList), + } + }, +) + +const healthChecks: HealthCheck[] = [ + { + title: "Missing Inbox Relays", + description: "Other people aren't currently able to reliably tag you in public notes.", + action: "Update", + isPending: context => context.readRelays.length <= 1, + apply: () => setReadRelays(DEFAULT_RELAYS), + }, + { + title: "Missing Outbox Relays", + description: "Other people aren't currently able to reliably find your public notes.", + action: "Update", + isPending: context => context.writeRelays.length <= 1, + apply: () => setWriteRelays(DEFAULT_RELAYS), + }, + { + title: "Missing DM Relays", + description: "You aren't currently able to reliably send or receive direct messages.", + action: "Update", + isPending: context => context.messagingRelays.length <= 1, + apply: () => setMessagingRelays(DEFAULT_MESSAGING_RELAYS), + }, + { + title: "Too Many Inbox Relays", + description: + "You have more inbox relays than is really necessary, which can affect resource usage.", + action: "Prune Selections", + isPending: context => context.readRelays.length > 8, + apply: context => setReadRelays(sample(5, context.readRelays)), + }, + { + title: "Too Many Outbox Relays", + description: + "You have more outbox relays than is really necessary, which can affect resource usage.", + action: "Prune Selections", + isPending: context => context.writeRelays.length > 8, + apply: context => setWriteRelays(sample(5, context.writeRelays)), + }, + { + title: "Too Many DM Relays", + description: + "You have more DM relays than is really necessary, which can affect resource usage.", + action: "Prune Selections", + isPending: context => context.messagingRelays.length > 8, + apply: context => setMessagingRelays(sample(5, context.messagingRelays)), + }, + { + title: "Invalid Search Relays", + description: "Some of your search relays don't support search.", + action: "Remove Invalid", + isPending: context => context.searchRelays.some(url => not(ifLet(getRelay(url), hasNip50))), + apply: context => + setSearchRelays(context.searchRelays.filter(url => ifLet(getRelay(url), hasNip50))), + }, +] + +export const isHealthCheckPending = (healthCheck: HealthCheck) => + healthCheck.isPending(get(healthCheckContext)) + +export const applyHealthCheck = (healthCheck: HealthCheck) => + healthCheck.apply(get(healthCheckContext)) + +export const pendingHealthChecks = derived(healthCheckContext, ctx => + healthChecks.filter(hc => hc.isPending(ctx)), +) diff --git a/src/routes/settings/relays/+page.svelte b/src/routes/settings/relays/+page.svelte index a9299931..210aaaab 100644 --- a/src/routes/settings/relays/+page.svelte +++ b/src/routes/settings/relays/+page.svelte @@ -23,7 +23,7 @@ import ForbiddenCircle from "@assets/icons/forbidden-circle.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import RelaySettingsItem from "@app/components/RelaySettingsItem.svelte" - import RelaySettingsActionItems from "@app/components/RelaySettingsActionItems.svelte" + import RelaySettingsHealthChecks from "@app/components/RelaySettingsHealthChecks.svelte" import {hasNip50} from "@app/core/state" import {discoverRelays} from "@app/core/requests" @@ -44,7 +44,7 @@
- +