debounce subscription syncing
All checks were successful
CI / lint-check-build (pull_request) Successful in 4m4s
All checks were successful
CI / lint-check-build (pull_request) Successful in 4m4s
This commit is contained in:
parent
cbba1035e7
commit
d6f0e47edf
1 changed files with 57 additions and 37 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import {hash, maybe, spec, throttle} from "@welshman/lib"
|
||||
import {call, hash, maybe, spec, throttle} from "@welshman/lib"
|
||||
import type {Filter} from "@welshman/util"
|
||||
import {Address, DELETE, MESSAGE, makeEvent, makeHttpAuth, makeHttpAuthHeader} from "@welshman/util"
|
||||
import {merged} from "@welshman/store"
|
||||
|
|
@ -75,50 +75,70 @@ const syncRelaySubscriptionsForEmail = (
|
|||
export class MailNotifications {
|
||||
_controller = maybe<AbortController>()
|
||||
|
||||
// In-flight register promise, so overlapping calls (settings page submit plus
|
||||
// Mail.sync) coalesce into a single PUT instead of racing two subscriptions.
|
||||
_register = maybe<Promise<void>>()
|
||||
|
||||
async register(email: string, frequency: string) {
|
||||
const $user = User.require(app.get())
|
||||
const $signer = $user.signer
|
||||
if (this._register) return this._register
|
||||
|
||||
if (!$signer) {
|
||||
emailNotificationState.set({error: "No signer available. Check your browser extension."})
|
||||
throw new Error("No signer available")
|
||||
}
|
||||
this._register = call(async () => {
|
||||
try {
|
||||
const $user = User.require(app.get())
|
||||
const $signer = $user.signer
|
||||
|
||||
if (!EMAIL_NOTIFICATION_SERVER) {
|
||||
emailNotificationState.set({error: "Email notification server is not configured."})
|
||||
throw new Error("Email notification server not configured")
|
||||
}
|
||||
if (!$signer) {
|
||||
emailNotificationState.set({
|
||||
error: "No signer available. Check your browser extension.",
|
||||
})
|
||||
throw new Error("No signer available")
|
||||
}
|
||||
|
||||
let authEvent
|
||||
try {
|
||||
authEvent = await $signer.sign(await makeHttpAuth(EMAIL_NOTIFICATION_SERVER, "PUT"))
|
||||
} catch (e) {
|
||||
emailNotificationState.set({error: "Failed to create authentication. Check your signer."})
|
||||
throw new Error("Failed to sign NIP-98 auth", {cause: e})
|
||||
}
|
||||
if (!EMAIL_NOTIFICATION_SERVER) {
|
||||
emailNotificationState.set({error: "Email notification server is not configured."})
|
||||
throw new Error("Email notification server not configured")
|
||||
}
|
||||
|
||||
const authHeader = makeHttpAuthHeader(authEvent)
|
||||
let authEvent
|
||||
try {
|
||||
authEvent = await $signer.sign(await makeHttpAuth(EMAIL_NOTIFICATION_SERVER, "PUT"))
|
||||
} catch (e) {
|
||||
emailNotificationState.set({
|
||||
error: "Failed to create authentication. Check your signer.",
|
||||
})
|
||||
throw new Error("Failed to sign NIP-98 auth", {cause: e})
|
||||
}
|
||||
|
||||
let res
|
||||
try {
|
||||
res = await fetch(buildUrl(EMAIL_NOTIFICATION_SERVER, "subscription", "email"), {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({email, frequency, pubkey: $user.pubkey}),
|
||||
headers: {Authorization: authHeader, "Content-Type": "application/json"},
|
||||
})
|
||||
} catch (e) {
|
||||
emailNotificationState.set({error: `Could not reach email server. Check your connection.`})
|
||||
throw new Error("Network error", {cause: e})
|
||||
}
|
||||
const authHeader = makeHttpAuthHeader(authEvent)
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => "unknown error")
|
||||
emailNotificationState.set({error: `Registration failed: ${text}`})
|
||||
throw new Error(`Registration failed: ${text}`)
|
||||
}
|
||||
let res
|
||||
try {
|
||||
res = await fetch(buildUrl(EMAIL_NOTIFICATION_SERVER, "subscription", "email"), {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({email, frequency, pubkey: $user.pubkey}),
|
||||
headers: {Authorization: authHeader, "Content-Type": "application/json"},
|
||||
})
|
||||
} catch (e) {
|
||||
emailNotificationState.set({
|
||||
error: `Could not reach email server. Check your connection.`,
|
||||
})
|
||||
throw new Error("Network error", {cause: e})
|
||||
}
|
||||
|
||||
const {key, callback} = await res.json()
|
||||
emailNotificationState.set({key, callback, email, frequency, error: undefined})
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => "unknown error")
|
||||
emailNotificationState.set({error: `Registration failed: ${text}`})
|
||||
throw new Error(`Registration failed: ${text}`)
|
||||
}
|
||||
|
||||
const {key, callback} = await res.json()
|
||||
emailNotificationState.set({key, callback, email, frequency, error: undefined})
|
||||
} finally {
|
||||
this._register = undefined
|
||||
}
|
||||
})
|
||||
|
||||
return this._register
|
||||
}
|
||||
|
||||
async unregister() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue