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 (