Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion components/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import useCookie from '@/components/use-cookie'
import Link from 'next/link'
import AddIcon from '@/svgs/add-fill.svg'
import { cookieOptions, MULTI_AUTH_ANON, MULTI_AUTH_LIST, MULTI_AUTH_POINTER } from '@/lib/auth'
import { abortPendingRequests } from '@/lib/apollo'

const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8')

export const nextAccount = async () => {
abortPendingRequests() // Cancel any pending requests during account switch
const { status } = await fetch('/api/next-account', { credentials: 'include' })
// if status is 302, this means the server was able to switch us to the next available account
return status === 302
Expand Down Expand Up @@ -69,7 +71,7 @@ const AccountListRow = ({ account, selected, ...props }) => {
const onClick = async (e) => {
// prevent navigation
e.preventDefault()

abortPendingRequests() // Cancel pending requests during account switch
// update pointer cookie
const options = cookieOptions({ httpOnly: false })
const anon = account.id === USER_ID.anon
Expand Down
4 changes: 3 additions & 1 deletion components/nav/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { useWalletIndicator } from '@/wallets/client/hooks'
import SwitchAccountList, { nextAccount, useAccounts } from '@/components/account'
import { useShowModal } from '@/components/modal'
import { numWithUnits } from '@/lib/format'
import { abortPendingRequests } from '@/lib/apollo'

export function Brand ({ className }) {
return (
Expand Down Expand Up @@ -305,7 +306,8 @@ function LogoutObstacle ({ onClose }) {
router.reload()
return
}

// Abort all pending GraphQL requests to prevent race condition
abortPendingRequests()
// order is important because we need to be logged in to delete push subscription on server
const pushSubscription = await swRegistration?.pushManager.getSubscription()
if (pushSubscription) {
Expand Down
35 changes: 34 additions & 1 deletion lib/apollo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApolloClient, InMemoryCache, HttpLink, makeVar, split, from } from '@apollo/client'
import { ApolloClient, InMemoryCache, HttpLink, makeVar, split, from, ApolloLink } from '@apollo/client'
import { BatchHttpLink } from '@apollo/client/link/batch-http'
import { decodeCursor, LIMIT } from './cursor'
import { COMMENTS_LIMIT, SSR } from './constants'
Expand Down Expand Up @@ -29,6 +29,36 @@ export default function getApolloClient () {
}

export const meAnonSats = {}
let globalAbortController = null
export function getGlobalAbortController () {
if (!globalAbortController || globalAbortController.signal.aborted) {
globalAbortController = new AbortController()
}
return globalAbortController
}

export function abortPendingRequests () {
if (globalAbortController && !globalAbortController.signal.aborted) {
globalAbortController.abort('Logout in progress')
console.log('Aborted pending GraphQL requests during logout')
}
}

const createAbortLink = () => new ApolloLink((operation, forward) => {
if (SSR) {
return forward(operation)
}

const abortController = getGlobalAbortController()
operation.setContext((context) => ({
...context,
fetchOptions: {
...context.fetchOptions,
signal: abortController.signal
}
}))
return forward(operation)
})

const retryLink = new RetryLink({
delay: {
Expand All @@ -46,8 +76,11 @@ const retryLink = new RetryLink({
})

function getClient (uri) {
const abortLink = createAbortLink()

const link = from([
retryLink,
abortLink,
split(
// batch zaps if wallet is enabled so they can be executed serially in a single request
operation => operation.operationName === 'act' && operation.variables.act === 'TIP' && operation.getContext().batch,
Expand Down