Skip to content

Commit ed1a672

Browse files
feat(dbrp): create DBRP context and store mappings in local storage (#6642)
* feat: add dbrp context that stores in local storage * chore: add lastFetch and reset local storage on ummount
1 parent 80e3e03 commit ed1a672

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

src/shared/contexts/dbrps.tsx

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Libraries
2+
import React, {createContext, FC, useEffect, useMemo, useRef} from 'react'
3+
import {createLocalStorageStateHook} from 'use-local-storage-state'
4+
5+
// Types
6+
import {DBRP, getDbrps, GetDbrpsParams} from 'src/client'
7+
import {QueryScope} from 'src/shared/contexts/query'
8+
import {RemoteDataState} from 'src/types'
9+
10+
interface DBRPContextType {
11+
loading: RemoteDataState
12+
dbrps: DBRP[]
13+
}
14+
15+
const DEFAULT_CONTEXT: DBRPContextType = {
16+
loading: RemoteDataState.NotStarted,
17+
dbrps: [],
18+
}
19+
20+
export const DBRPContext = createContext<DBRPContextType>(DEFAULT_CONTEXT)
21+
22+
const DBRP_LOCAL_STORAGE_KEY = 'dbrps'
23+
const useLocalStorageState = createLocalStorageStateHook(
24+
DBRP_LOCAL_STORAGE_KEY,
25+
{}
26+
)
27+
28+
interface Props {
29+
scope: QueryScope
30+
}
31+
32+
export const DBRPProvider: FC<Props> = ({children, scope}) => {
33+
const cacheKey = `${scope.region};;<${scope.org}>`
34+
const [dbrpCache, setDBRPCache] = useLocalStorageState()
35+
const dbrps = dbrpCache[cacheKey]?.dbrps ?? DEFAULT_CONTEXT.dbrps
36+
const lastFetch = dbrpCache[cacheKey]?.lastFetch ?? 0
37+
const loading = dbrpCache[cacheKey]?.loading ?? DEFAULT_CONTEXT.loading
38+
const controller = useRef<AbortController>(null)
39+
40+
useEffect(() => {
41+
if (controller.current) {
42+
return () => {
43+
try {
44+
// Cancelling active query so that there's no memory leak
45+
// in this component when unmounting
46+
controller.current.abort()
47+
} catch (e) {
48+
// Do nothing
49+
}
50+
}
51+
}
52+
}, [controller])
53+
54+
// make sure to fetch dbrps on mount
55+
useEffect(() => {
56+
const TWELVE_HOURS = 12 * 60 * 60 * 1000
57+
if (Date.now() - lastFetch > TWELVE_HOURS) {
58+
fetchDBRPs()
59+
} else if (loading === RemoteDataState.NotStarted) {
60+
fetchDBRPs()
61+
}
62+
63+
return () => {
64+
// reset the dbrp in local storage on ummount
65+
// using `window.localStorage` since `createLocalStorageStateHook` has a bug
66+
// to set local storage to an empty {}
67+
window.localStorage.setItem(DBRP_LOCAL_STORAGE_KEY, JSON.stringify({}))
68+
}
69+
}, [])
70+
71+
const updateCache = (update: any): void => {
72+
dbrpCache[cacheKey] = {
73+
...dbrpCache[cacheKey],
74+
...update,
75+
}
76+
setDBRPCache({...dbrpCache})
77+
}
78+
79+
const fetchDBRPs = (): void => {
80+
if (controller.current) {
81+
controller.current.abort()
82+
controller.current = null
83+
} else {
84+
controller.current = new AbortController()
85+
}
86+
87+
updateCache({loading: RemoteDataState.Loading})
88+
89+
getDbrps({
90+
query: {
91+
orgID: scope.org,
92+
},
93+
} as GetDbrpsParams)
94+
.then(resp => {
95+
if (resp.status !== 200) {
96+
throw new Error(resp.data.message)
97+
}
98+
99+
updateCache({
100+
loading: RemoteDataState.Done,
101+
lastFetch: Date.now(),
102+
dbrps: resp.data.content,
103+
})
104+
})
105+
.catch(error => {
106+
console.error({error})
107+
controller.current = null
108+
updateCache({
109+
loading: RemoteDataState.Error,
110+
})
111+
})
112+
}
113+
114+
return useMemo(
115+
() => (
116+
<DBRPContext.Provider value={{loading, dbrps}}>
117+
{children}
118+
</DBRPContext.Provider>
119+
),
120+
[loading, dbrps]
121+
)
122+
}

0 commit comments

Comments
 (0)