diff --git a/modules/app/components/TxIndicators.tsx b/modules/app/components/TxIndicators.tsx index 7b2bfffe6..73a2b9038 100644 --- a/modules/app/components/TxIndicators.tsx +++ b/modules/app/components/TxIndicators.tsx @@ -8,7 +8,6 @@ SPDX-License-Identifier: AGPL-3.0-or-later import { Box, ThemeUIStyleObject } from 'theme-ui'; import { useEffect } from 'react'; -import lottie from 'lottie-web'; import txFailedAnimation from 'lib/animation/txFailed.json'; import txSuccessAnimation from 'lib/animation/txSuccess.json'; @@ -16,14 +15,23 @@ import txPendingAnimation from 'lib/animation/txPending.json'; const Failed = ({ done, ...props }: { done?: () => void; sx?: ThemeUIStyleObject }): React.ReactElement => { useEffect(() => { - const animation = lottie.loadAnimation({ - container: document.getElementById('tx-failed-animation-container') as HTMLElement, - loop: false, - autoplay: true, - animationData: txFailedAnimation - }); - - done && animation.addEventListener('complete', () => setTimeout(done, 200)); + const loadLottie = async () => { + const lottie = await import('lottie-web'); + const animation = lottie.default.loadAnimation({ + container: document.getElementById('tx-failed-animation-container') as HTMLElement, + loop: false, + autoplay: true, + animationData: txFailedAnimation + }); + + done && animation.addEventListener('complete', () => setTimeout(done, 200)); + + return () => { + animation.destroy(); + }; + }; + + loadLottie(); }, []); return ; @@ -31,14 +39,23 @@ const Failed = ({ done, ...props }: { done?: () => void; sx?: ThemeUIStyleObject const Success = ({ done, ...props }: { done?: () => void; sx?: ThemeUIStyleObject }): React.ReactElement => { useEffect(() => { - const animation = lottie.loadAnimation({ - container: document.getElementById('tx-success-animation-container') as HTMLElement, - loop: false, - autoplay: true, - animationData: txSuccessAnimation - }); - - done && animation.addEventListener('complete', () => setTimeout(done, 200)); + const loadLottie = async () => { + const lottie = await import('lottie-web'); + const animation = lottie.default.loadAnimation({ + container: document.getElementById('tx-success-animation-container') as HTMLElement, + loop: false, + autoplay: true, + animationData: txSuccessAnimation + }); + + done && animation.addEventListener('complete', () => setTimeout(done, 200)); + + return () => { + animation.destroy(); + }; + }; + + loadLottie(); }, []); return ; @@ -46,14 +63,23 @@ const Success = ({ done, ...props }: { done?: () => void; sx?: ThemeUIStyleObjec const Pending = ({ done, ...props }: { done?: () => void; sx?: ThemeUIStyleObject }): React.ReactElement => { useEffect(() => { - const animation = lottie.loadAnimation({ - container: document.getElementById('tx-pending-animation-container') as HTMLElement, - loop: true, - autoplay: true, - animationData: txPendingAnimation - }); - - done && animation.addEventListener('complete', () => setTimeout(done, 200)); + const loadLottie = async () => { + const lottie = await import('lottie-web'); + const animation = lottie.default.loadAnimation({ + container: document.getElementById('tx-pending-animation-container') as HTMLElement, + loop: true, + autoplay: true, + animationData: txPendingAnimation + }); + + done && animation.addEventListener('complete', () => setTimeout(done, 200)); + + return () => { + animation.destroy(); + }; + }; + + loadLottie(); }, []); return ; diff --git a/modules/cache/cache.ts b/modules/cache/cache.ts index f1c9db1be..2d7b9ef42 100644 --- a/modules/cache/cache.ts +++ b/modules/cache/cache.ts @@ -55,11 +55,30 @@ export const cacheDel = (name: string, network: SupportedNetworks, expiryMs?: nu if (redisCacheEnabled()) { // if clearing proposals, we need to find all of them first if (name === 'proposals') { - redis?.keys('*proposals*').then(keys => { - keys.forEach(key => { - logger.debug('cacheDel key: ', key); - redis?.del(key); - }); + const deleteProposalKeys = async () => { + let cursor = '0'; + do { + const pipeline = (redis as Redis).pipeline(); + const [nextCursor, keys] = await (redis as Redis).scan( + cursor, + 'MATCH', + '*proposals*', + 'COUNT', + '100' + ); + + if (keys.length > 0) { + logger.debug('cacheDel pattern: *proposals* ', cursor, keys.length); + pipeline.del(...keys); + } + + await pipeline.exec(); + cursor = nextCursor; + } while (cursor !== '0'); + }; + + deleteProposalKeys().catch(error => { + logger.error('Error deleting proposal keys:', error); }); } else { // otherwise just delete the file based on path @@ -90,8 +109,8 @@ export const getCacheInfo = async (name: string, network: SupportedNetworks): Pr // if fetching proposals cache info, there are likely multiple keys cached due to different query params // we'll return the ttl for first proposals key we find if (name === executiveProposalsCacheKey) { - const keys = await redis?.keys('*proposals*'); - if (keys && keys.length > 0) { + const [, keys] = await (redis as Redis).scan('0', 'MATCH', '*proposals*', 'COUNT', '1'); + if (keys.length > 0) { const ttl = await redis?.ttl(keys[0]); return ttl; } diff --git a/modules/polling/components/MobileVoteSheet.tsx b/modules/polling/components/MobileVoteSheet.tsx index 7d1e1496a..380fa3ebd 100644 --- a/modules/polling/components/MobileVoteSheet.tsx +++ b/modules/polling/components/MobileVoteSheet.tsx @@ -12,7 +12,6 @@ import { Text, Button, Box, Flex } from 'theme-ui'; import invariant from 'tiny-invariant'; import range from 'lodash/range'; import isNil from 'lodash/isNil'; -import lottie from 'lottie-web'; import { Poll } from 'modules/polling/types'; import Stack from 'modules/app/components/layout/layouts/Stack'; import { useRouter } from 'next/router'; @@ -198,14 +197,23 @@ export default function MobileVoteSheet({ const AddingView = ({ done }: { done: () => void }) => { useEffect(() => { - const animation = lottie.loadAnimation({ - container: document.getElementById('ballot-animation-container') as HTMLElement, - loop: false, - autoplay: true, - animationData: ballotAnimation - }); - - animation.addEventListener('complete', () => setTimeout(done, 200)); + const loadLottie = async () => { + const lottie = await import('lottie-web'); + const animation = lottie.default.loadAnimation({ + container: document.getElementById('ballot-animation-container') as HTMLElement, + loop: false, + autoplay: true, + animationData: ballotAnimation + }); + + animation.addEventListener('complete', () => setTimeout(done, 200)); + + return () => { + animation.destroy(); + }; + }; + + loadLottie(); }, []); return (