1
1
import { createAsyncThunk , createSelector , createSlice } from "@reduxjs/toolkit" ;
2
2
3
+ const CACHE_NAME = "v1" ;
4
+ // Delete all caches older than 6 hours
5
+ const cacheRefreshIntervalInMilliseconds = 6 * 3600 * 1000 ;
6
+
3
7
export const poolsSlice = createSlice ( {
4
8
name : 'pools' ,
5
9
initialState : { list : [ ] } ,
6
- reducers : { } ,
10
+ reducers : {
11
+ refreshPoolsCaches : ( state ) => {
12
+ const now = Date . now ( ) ;
13
+ for ( const entry of state . list . map ( p => ( { date : p . date , url : poolTickersUrl ( p . aggregator ) } ) ) ) {
14
+ const millisecondsSinceLastRefresh = now - entry . date ;
15
+
16
+ if ( millisecondsSinceLastRefresh > cacheRefreshIntervalInMilliseconds ) {
17
+ caches . open ( CACHE_NAME ) . then ( async ( cache ) => {
18
+ const deletionSuccessful = await cache . delete ( entry . url ) ;
19
+ if ( ! deletionSuccessful ) {
20
+ console . error ( `Failed to delete cache: ${ entry . url } ` ) ;
21
+ }
22
+ } ) ;
23
+ }
24
+ }
25
+ }
26
+ } ,
7
27
extraReducers : builder => builder . addCase ( updatePoolsForAggregator . fulfilled , ( state , action ) => {
8
28
let existing = poolsForAggregator ( state , action . payload . aggregator ) ;
9
29
10
30
if ( existing ) {
11
- existing . date = action . payload . date ;
31
+ existing . network = action . payload . network ;
12
32
existing . pools = action . payload . pools ;
13
33
} else {
14
34
state . list . push ( {
@@ -21,22 +41,53 @@ export const poolsSlice = createSlice({
21
41
} )
22
42
} ) ;
23
43
44
+ export const {
45
+ refreshPoolsCaches
46
+ } = poolsSlice . actions ;
47
+
48
+ const poolTickersUrl = aggregator => `${ aggregator } /signers/tickers` ;
49
+
24
50
export const updatePoolsForAggregator = createAsyncThunk ( 'pools/updateForAggregator' , aggregator => {
25
- return fetch ( `${ aggregator } /signers/tickers` )
51
+ const url = poolTickersUrl ( aggregator ) ;
52
+ return caches . match ( url )
53
+ . then ( cached => {
54
+ // Cache hit
55
+ if ( cached ) {
56
+ return cached ;
57
+ }
58
+
59
+ // Cache miss
60
+ return fetch ( url ) . then ( response => {
61
+ if ( response . status === 200 ) {
62
+ caches . open ( CACHE_NAME ) . then ( async ( cache ) => {
63
+ const putSuccessful = await cache . put ( url , response ) ;
64
+ if ( ! putSuccessful ) {
65
+ console . error ( `Failed to put cache: ${ url } ` ) ;
66
+ }
67
+ } ) ;
68
+ }
69
+ return response . clone ( ) ;
70
+ } )
71
+ } )
26
72
. then ( response => response . status === 200 ? response . json ( ) : { } )
27
73
. then ( data => {
28
74
return {
29
75
aggregator : aggregator ,
30
76
date : Date . now ( ) ,
31
77
network : data . network ,
32
- pools : data . signers ,
78
+ pools : data . signers ?? [ ] ,
33
79
} ;
34
80
} ) ;
35
81
} ) ;
36
82
37
- const poolsForAggregator = ( state , aggregator ) => {
38
- return state . list . find ( poolsData => poolsData . aggregator === aggregator ) ;
39
- } ;
83
+ const poolsForAggregator = createSelector ( [
84
+ state => state . pools ,
85
+ ( state , aggregator ) => aggregator
86
+ ] ,
87
+ ( pools , aggregator ) => {
88
+ return pools . list . find ( poolsData => poolsData . aggregator === aggregator ) ;
89
+ }
90
+ ) ;
40
91
41
92
export const getPool = createSelector ( [
42
93
state => state . pools ,
0 commit comments