3
3
checkPaidMembershipFromEntra ,
4
4
checkPaidMembershipFromTable ,
5
5
setPaidMembershipInTable ,
6
+ MEMBER_CACHE_SECONDS ,
6
7
} from "api/functions/membership.js" ;
7
8
import { validateNetId } from "api/functions/validation.js" ;
8
9
import { FastifyPluginAsync } from "fastify" ;
@@ -26,9 +27,7 @@ import rawbody from "fastify-raw-body";
26
27
import { FastifyZodOpenApiTypeProvider } from "fastify-zod-openapi" ;
27
28
import { z } from "zod" ;
28
29
import { withTags } from "api/components/index.js" ;
29
-
30
- const NONMEMBER_CACHE_SECONDS = 60 ; // 1 minute
31
- const MEMBER_CACHE_SECONDS = 43200 ; // 12 hours
30
+ import { getKey , setKey } from "api/functions/redisCache.js" ;
32
31
33
32
const membershipPlugin : FastifyPluginAsync = async ( fastify , _options ) => {
34
33
await fastify . register ( rawbody , {
@@ -89,7 +88,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
89
88
} ,
90
89
async ( request , reply ) => {
91
90
const netId = request . params . netId . toLowerCase ( ) ;
92
- if ( fastify . nodeCache . get ( `isMember_${ netId } ` ) === true ) {
91
+ const cacheKey = `membership:${ netId } :acmpaid` ;
92
+ const result = await getKey < { isMember : boolean } > ( {
93
+ redisClient : fastify . redisClient ,
94
+ key : cacheKey ,
95
+ logger : request . log ,
96
+ } ) ;
97
+ if ( result && result . isMember ) {
93
98
throw new ValidationError ( {
94
99
message : `${ netId } is already a paid member!` ,
95
100
} ) ;
@@ -99,11 +104,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
99
104
fastify . dynamoClient ,
100
105
) ;
101
106
if ( isDynamoMember ) {
102
- fastify . nodeCache . set (
103
- `isMember_${ netId } ` ,
104
- true ,
105
- MEMBER_CACHE_SECONDS ,
106
- ) ;
107
+ await setKey ( {
108
+ redisClient : fastify . redisClient ,
109
+ key : cacheKey ,
110
+ data : JSON . stringify ( { isMember : true } ) ,
111
+ expiresIn : MEMBER_CACHE_SECONDS ,
112
+ logger : request . log ,
113
+ } ) ;
107
114
throw new ValidationError ( {
108
115
message : `${ netId } is already a paid member!` ,
109
116
} ) ;
@@ -121,11 +128,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
121
128
paidMemberGroup ,
122
129
) ;
123
130
if ( isAadMember ) {
124
- fastify . nodeCache . set (
125
- `isMember_${ netId } ` ,
126
- true ,
127
- MEMBER_CACHE_SECONDS ,
128
- ) ;
131
+ await setKey ( {
132
+ redisClient : fastify . redisClient ,
133
+ key : cacheKey ,
134
+ data : JSON . stringify ( { isMember : true } ) ,
135
+ expiresIn : MEMBER_CACHE_SECONDS ,
136
+ logger : request . log ,
137
+ } ) ;
129
138
reply
130
139
. header ( "X-ACM-Data-Source" , "aad" )
131
140
. send ( { netId, isPaidMember : true } ) ;
@@ -134,11 +143,14 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
134
143
message : `${ netId } is already a paid member!` ,
135
144
} ) ;
136
145
}
137
- fastify . nodeCache . set (
138
- `isMember_${ netId } ` ,
139
- false ,
140
- NONMEMBER_CACHE_SECONDS ,
141
- ) ;
146
+ // Once the caller becomes a member, the stripe webhook will handle changing this to true
147
+ await setKey ( {
148
+ redisClient : fastify . redisClient ,
149
+ key : cacheKey ,
150
+ data : JSON . stringify ( { isMember : false } ) ,
151
+ expiresIn : MEMBER_CACHE_SECONDS ,
152
+ logger : request . log ,
153
+ } ) ;
142
154
const secretApiConfig =
143
155
( await getSecretValue (
144
156
fastify . secretsManagerClient ,
@@ -190,11 +202,19 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
190
202
async ( request , reply ) => {
191
203
const netId = request . params . netId . toLowerCase ( ) ;
192
204
const list = request . query . list || "acmpaid" ;
193
- if ( fastify . nodeCache . get ( `isMember_${ netId } _${ list } ` ) !== undefined ) {
205
+ // we don't control external list as its direct upload in Dynamo, cache only for 60 seconds.
206
+ const ourCacheSeconds = list === "acmpaid" ? MEMBER_CACHE_SECONDS : 60 ;
207
+ const cacheKey = `membership:${ netId } :${ list } ` ;
208
+ const result = await getKey < { isMember : boolean } > ( {
209
+ redisClient : fastify . redisClient ,
210
+ key : cacheKey ,
211
+ logger : request . log ,
212
+ } ) ;
213
+ if ( result ) {
194
214
return reply . header ( "X-ACM-Data-Source" , "cache" ) . send ( {
195
215
netId,
196
216
list : list === "acmpaid" ? undefined : list ,
197
- isPaidMember : fastify . nodeCache . get ( `isMember_ ${ netId } _ ${ list } ` ) ,
217
+ isPaidMember : result . isMember ,
198
218
} ) ;
199
219
}
200
220
if ( list !== "acmpaid" ) {
@@ -203,11 +223,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
203
223
list ,
204
224
fastify . dynamoClient ,
205
225
) ;
206
- fastify . nodeCache . set (
207
- `isMember_${ netId } _${ list } ` ,
208
- isMember ,
209
- MEMBER_CACHE_SECONDS ,
210
- ) ;
226
+ await setKey ( {
227
+ redisClient : fastify . redisClient ,
228
+ key : cacheKey ,
229
+ data : JSON . stringify ( { isMember } ) ,
230
+ expiresIn : ourCacheSeconds ,
231
+ logger : request . log ,
232
+ } ) ;
211
233
return reply . header ( "X-ACM-Data-Source" , "dynamo" ) . send ( {
212
234
netId,
213
235
list,
@@ -219,11 +241,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
219
241
fastify . dynamoClient ,
220
242
) ;
221
243
if ( isDynamoMember ) {
222
- fastify . nodeCache . set (
223
- `isMember_${ netId } _${ list } ` ,
224
- true ,
225
- MEMBER_CACHE_SECONDS ,
226
- ) ;
244
+ await setKey ( {
245
+ redisClient : fastify . redisClient ,
246
+ key : cacheKey ,
247
+ data : JSON . stringify ( { isMember : true } ) ,
248
+ expiresIn : ourCacheSeconds ,
249
+ logger : request . log ,
250
+ } ) ;
227
251
return reply
228
252
. header ( "X-ACM-Data-Source" , "dynamo" )
229
253
. send ( { netId, isPaidMember : true } ) ;
@@ -241,22 +265,26 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
241
265
paidMemberGroup ,
242
266
) ;
243
267
if ( isAadMember ) {
244
- fastify . nodeCache . set (
245
- `isMember_${ netId } _${ list } ` ,
246
- true ,
247
- MEMBER_CACHE_SECONDS ,
248
- ) ;
268
+ await setKey ( {
269
+ redisClient : fastify . redisClient ,
270
+ key : cacheKey ,
271
+ data : JSON . stringify ( { isMember : true } ) ,
272
+ expiresIn : ourCacheSeconds ,
273
+ logger : request . log ,
274
+ } ) ;
249
275
reply
250
276
. header ( "X-ACM-Data-Source" , "aad" )
251
277
. send ( { netId, isPaidMember : true } ) ;
252
278
await setPaidMembershipInTable ( netId , fastify . dynamoClient ) ;
253
279
return ;
254
280
}
255
- fastify . nodeCache . set (
256
- `isMember_${ netId } _${ list } ` ,
257
- false ,
258
- NONMEMBER_CACHE_SECONDS ,
259
- ) ;
281
+ await setKey ( {
282
+ redisClient : fastify . redisClient ,
283
+ key : cacheKey ,
284
+ data : JSON . stringify ( { isMember : false } ) ,
285
+ expiresIn : ourCacheSeconds ,
286
+ logger : request . log ,
287
+ } ) ;
260
288
return reply
261
289
. header ( "X-ACM-Data-Source" , "aad" )
262
290
. send ( { netId, isPaidMember : false } ) ;
@@ -315,6 +343,7 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
315
343
) {
316
344
const customerEmail = event . data . object . customer_email ;
317
345
if ( ! customerEmail ) {
346
+ request . log . info ( "No customer email found." ) ;
318
347
return reply
319
348
. code ( 200 )
320
349
. send ( { handled : false , requestId : request . id } ) ;
0 commit comments