1import * as Context from "effect/Context";
2import * as Layer from "effect/Layer";
3import type * as Stream from "effect/Stream";
4
5export type ConnectionWakeup =
6 | "application-active"
7 | "application-active-probe"
8 | "application-active-reconnect"
9 | "credentials-changed"
10 // The device moved to a different network (another Wi-Fi, Wi-Fi to
11 // cellular) while staying online. Saved routes may have changed reach.
12 | "network-changed";
13
14function isApplicationActiveWakeup(reason: ConnectionWakeup): boolean {
15 return (
16 reason === "application-active" ||
17 reason === "application-active-probe" ||
18 reason === "application-active-reconnect"
19 );
20}
21
22/** Conditions changed enough that a pending retry should run now, from the first rung. */
23export function resetsRetryBackoff(reason: ConnectionWakeup): boolean {
24 return isApplicationActiveWakeup(reason) || reason === "network-changed";
25}
26
27// A long resume replaces the session, and the new session subscribes on its own.
28export function shouldResubscribeAfterWakeup(reason: ConnectionWakeup): boolean {
29 return reason === "application-active" || reason === "application-active-probe";
30}
31
32export class ConnectionWakeups extends Context.Service<
33 ConnectionWakeups,
34 {
35 readonly changes: Stream.Stream<ConnectionWakeup>;
36 }
37>()("@t3tools/client-runtime/connection/wakeups/ConnectionWakeups") {}
38
39const make = (service: ConnectionWakeups["Service"]) => ConnectionWakeups.of(service);
40
41export const layer = (service: ConnectionWakeups["Service"]) =>
42 Layer.succeed(ConnectionWakeups, make(service));