Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
feat: use subscription to listen for certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastiendan committed Nov 27, 2023
1 parent b57e07c commit 1baedb1
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 126 deletions.
5 changes: 5 additions & 0 deletions src/__generated__/gql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion src/__generated__/graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

140 changes: 15 additions & 125 deletions src/hooks/useSubnetSubscribeToCertificates.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { useQuery } from '@apollo/client'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useSubscription } from '@apollo/client'
import { useEffect, useState } from 'react'

import { graphql } from '../__generated__/gql'
// import { ErrorsContext } from '../contexts/errors'
import { Certificate } from '../types'
import { SourceStreamPosition } from '../__generated__/graphql'
import { SubnetFilter } from '../__generated__/graphql'

const DEFAULT_LIMIT = 10

const GET_CERTIFICATES = graphql(`
query Certificates($fromSourceCheckpoint: SourceCheckpoint!, $limit: Int!) {
certificates(fromSourceCheckpoint: $fromSourceCheckpoint, first: $limit) {
const WATCH_CERTIFICATES = graphql(`
subscription OnCertificates($filter: SubnetFilter) {
watchDeliveredCertificates(filter: $filter) {
prevId
id
proof
Expand All @@ -30,130 +27,23 @@ const GET_CERTIFICATES = graphql(`
`)

interface Options {
limit?: number
sourceSubnetIds?: Array<SourceStreamPosition>
filter?: SubnetFilter
}

export default function useSubnetSubscribeToCertificates({
limit,
sourceSubnetIds,
}: Options) {
// const { setErrors } = React.useContext(ErrorsContext)
export default function useSubnetSubscribeToCertificates({ filter }: Options) {
const [certificates, setCertificates] = useState<Certificate[]>([])
const [currentIndexes, setCurrentIndexes] = useState(
new Map<string, number>()
)
const currentIndexesRef = useRef<Map<string, number> | null>(null)
const [storedPositions, setStoredPositions] = useState(
new Map<string, number>()
)
const uniqueSourceSubnetId = useRef<string | null>(null)
const definedLimit = useMemo(() => limit || DEFAULT_LIMIT, [limit])

useEffect(
function storeLatestCurrentIndexes() {
window.setTimeout(() => {
currentIndexesRef.current = currentIndexes
}, 500)
},
[currentIndexes]
)

useEffect(
function onNewSourceSubnetIds() {
let newStoredPositions = storedPositions
let newCurrentIndexes = currentIndexes

sourceSubnetIds?.forEach(({ position, sourceSubnetId }) => {
if (
storedPositions.get(sourceSubnetId.value) === undefined &&
position !== undefined
) {
newStoredPositions.set(sourceSubnetId.value, position)
newCurrentIndexes.set(sourceSubnetId.value, 0)
}
})

// Temp: clean certificates when subscription is to one subnet only and that subnet changes
if (
sourceSubnetIds?.length === 1 &&
sourceSubnetIds[0].sourceSubnetId.value !== uniqueSourceSubnetId.current
) {
uniqueSourceSubnetId.current = sourceSubnetIds[0].sourceSubnetId.value
newStoredPositions = new Map<string, number>()
newCurrentIndexes = new Map<string, number>()
newCurrentIndexes.set(sourceSubnetIds[0].sourceSubnetId.value, 0)
setCertificates([])
}

setStoredPositions(newStoredPositions)
setCurrentIndexes(newCurrentIndexes)
},
[sourceSubnetIds]
)

const { data, error, loading } = useQuery(GET_CERTIFICATES, {
const { data, error, loading } = useSubscription(WATCH_CERTIFICATES, {
variables: {
fromSourceCheckpoint: {
sourceSubnetIds: Array.from(storedPositions).map(([id]) => ({
value: id,
})),
positions: Array.from(storedPositions).map(([id, position]) => {
return {
sourceSubnetId: { value: id },
position: position
? (currentIndexesRef.current?.get(id) || 0) + position
: Infinity,
}
}),
},
limit: definedLimit,
filter,
},
pollInterval: 2000,
})

useEffect(
function appendCertificate() {
const latestCurrentIndexes = currentIndexesRef.current

if (
data?.certificates &&
data?.certificates.length &&
latestCurrentIndexes
) {
const newCurrentIndexes = latestCurrentIndexes
const newCertificates: Certificate[] = []

data.certificates.forEach((certificate) => {
const currentIndex = newCurrentIndexes.get(
certificate.sourceSubnetId.value
)

if (currentIndex !== undefined) {
newCurrentIndexes.set(
certificate.sourceSubnetId.value,
currentIndex + 1
)

const sourcePosition = storedPositions.get(
certificate.sourceSubnetId.value
)
newCertificates.push({
...certificate,
position: sourcePosition
? sourcePosition + currentIndex
: undefined,
})
}
})

setCurrentIndexes(newCurrentIndexes)
setCertificates((c) => [...newCertificates, ...c])
}
},
[data?.certificates]
)
console.log(certificates)
useEffect(() => {
if (data && data.watchDeliveredCertificates) {
setCertificates((c) => [data.watchDeliveredCertificates, ...c])
}
}, [data])

return { certificates, error, loading }
}

0 comments on commit 1baedb1

Please sign in to comment.