33 checkPaidMembershipFromEntra ,
44 checkPaidMembershipFromTable ,
55 setPaidMembershipInTable ,
6+ MEMBER_CACHE_SECONDS ,
67} from "api/functions/membership.js" ;
78import { validateNetId } from "api/functions/validation.js" ;
89import { FastifyPluginAsync } from "fastify" ;
@@ -26,9 +27,7 @@ import rawbody from "fastify-raw-body";
2627import { FastifyZodOpenApiTypeProvider } from "fastify-zod-openapi" ;
2728import { z } from "zod" ;
2829import { 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" ;
3231
3332const membershipPlugin : FastifyPluginAsync = async ( fastify , _options ) => {
3433 await fastify . register ( rawbody , {
@@ -89,7 +88,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
8988 } ,
9089 async ( request , reply ) => {
9190 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 ) {
9398 throw new ValidationError ( {
9499 message : `${ netId } is already a paid member!` ,
95100 } ) ;
@@ -99,11 +104,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
99104 fastify . dynamoClient ,
100105 ) ;
101106 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+ } ) ;
107114 throw new ValidationError ( {
108115 message : `${ netId } is already a paid member!` ,
109116 } ) ;
@@ -121,11 +128,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
121128 paidMemberGroup ,
122129 ) ;
123130 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+ } ) ;
129138 reply
130139 . header ( "X-ACM-Data-Source" , "aad" )
131140 . send ( { netId, isPaidMember : true } ) ;
@@ -134,11 +143,14 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
134143 message : `${ netId } is already a paid member!` ,
135144 } ) ;
136145 }
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+ } ) ;
142154 const secretApiConfig =
143155 ( await getSecretValue (
144156 fastify . secretsManagerClient ,
@@ -190,11 +202,19 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
190202 async ( request , reply ) => {
191203 const netId = request . params . netId . toLowerCase ( ) ;
192204 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 ) {
194214 return reply . header ( "X-ACM-Data-Source" , "cache" ) . send ( {
195215 netId,
196216 list : list === "acmpaid" ? undefined : list ,
197- isPaidMember : fastify . nodeCache . get ( `isMember_ ${ netId } _ ${ list } ` ) ,
217+ isPaidMember : result . isMember ,
198218 } ) ;
199219 }
200220 if ( list !== "acmpaid" ) {
@@ -203,11 +223,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
203223 list ,
204224 fastify . dynamoClient ,
205225 ) ;
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+ } ) ;
211233 return reply . header ( "X-ACM-Data-Source" , "dynamo" ) . send ( {
212234 netId,
213235 list,
@@ -219,11 +241,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
219241 fastify . dynamoClient ,
220242 ) ;
221243 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+ } ) ;
227251 return reply
228252 . header ( "X-ACM-Data-Source" , "dynamo" )
229253 . send ( { netId, isPaidMember : true } ) ;
@@ -241,22 +265,26 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
241265 paidMemberGroup ,
242266 ) ;
243267 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+ } ) ;
249275 reply
250276 . header ( "X-ACM-Data-Source" , "aad" )
251277 . send ( { netId, isPaidMember : true } ) ;
252278 await setPaidMembershipInTable ( netId , fastify . dynamoClient ) ;
253279 return ;
254280 }
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+ } ) ;
260288 return reply
261289 . header ( "X-ACM-Data-Source" , "aad" )
262290 . send ( { netId, isPaidMember : false } ) ;
@@ -315,6 +343,7 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
315343 ) {
316344 const customerEmail = event . data . object . customer_email ;
317345 if ( ! customerEmail ) {
346+ request . log . info ( "No customer email found." ) ;
318347 return reply
319348 . code ( 200 )
320349 . send ( { handled : false , requestId : request . id } ) ;
0 commit comments