2023-01-03 19:55:46 +00:00
|
|
|
// Copyright 2019 Signal Messenger, LLC
|
2020-10-30 20:34:04 +00:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2020-09-14 21:56:35 +00:00
|
|
|
/* eslint-disable no-console */
|
|
|
|
|
2024-11-18 19:20:23 +00:00
|
|
|
import type { Middleware, Store, UnknownAction } from 'redux';
|
2021-10-26 19:15:33 +00:00
|
|
|
import { applyMiddleware, createStore as reduxCreateStore } from 'redux';
|
2019-01-14 21:49:58 +00:00
|
|
|
|
|
|
|
import promise from 'redux-promise-middleware';
|
2024-11-18 19:20:23 +00:00
|
|
|
import { thunk } from 'redux-thunk';
|
2019-01-14 21:49:58 +00:00
|
|
|
import { createLogger } from 'redux-logger';
|
|
|
|
|
2024-08-29 13:30:27 +00:00
|
|
|
import * as log from '../logging/log';
|
2021-10-26 19:15:33 +00:00
|
|
|
import type { StateType } from './reducer';
|
|
|
|
import { reducer } from './reducer';
|
2021-08-18 20:08:14 +00:00
|
|
|
import { dispatchItemsMiddleware } from '../shims/dispatchItemsMiddleware';
|
2024-08-29 13:30:27 +00:00
|
|
|
import { isOlderThan } from '../util/timestamp';
|
|
|
|
import { SECOND } from '../util/durations';
|
2024-09-04 18:12:45 +00:00
|
|
|
import { getEnvironment } from '../environment';
|
2020-09-14 21:56:35 +00:00
|
|
|
|
|
|
|
declare global {
|
2021-01-14 18:07:05 +00:00
|
|
|
// We want to extend `window`'s properties, so we need an interface.
|
2022-06-03 21:07:51 +00:00
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
2020-09-14 21:56:35 +00:00
|
|
|
interface Console {
|
|
|
|
_log: Console['log'];
|
|
|
|
}
|
|
|
|
}
|
2019-01-14 21:49:58 +00:00
|
|
|
|
2024-09-04 18:12:45 +00:00
|
|
|
const env = getEnvironment();
|
2019-01-14 21:49:58 +00:00
|
|
|
|
|
|
|
// So Redux logging doesn't go to disk, and so we can get colors/styles
|
|
|
|
const directConsole = {
|
|
|
|
log: console._log,
|
|
|
|
groupCollapsed: console.groupCollapsed,
|
|
|
|
group: console.group,
|
|
|
|
groupEnd: console.groupEnd,
|
|
|
|
warn: console.warn,
|
|
|
|
error: console.error,
|
|
|
|
};
|
|
|
|
|
|
|
|
const logger = createLogger({
|
|
|
|
logger: directConsole,
|
2020-12-18 19:27:43 +00:00
|
|
|
predicate: (_getState, action) => {
|
|
|
|
if (action.type === 'network/CHECK_NETWORK_STATUS') {
|
|
|
|
return false;
|
|
|
|
}
|
2022-08-31 22:58:05 +00:00
|
|
|
if (action.type === 'calling/GROUP_CALL_AUDIO_LEVELS_CHANGE') {
|
|
|
|
return false;
|
|
|
|
}
|
2020-12-18 19:27:43 +00:00
|
|
|
return true;
|
|
|
|
},
|
2019-01-14 21:49:58 +00:00
|
|
|
});
|
|
|
|
|
2024-08-29 13:30:27 +00:00
|
|
|
const ACTION_COUNT_THRESHOLD = 25;
|
|
|
|
type ActionStats = {
|
|
|
|
timestamp: number;
|
|
|
|
names: Array<string>;
|
|
|
|
};
|
|
|
|
const actionStats: ActionStats = {
|
|
|
|
timestamp: Date.now(),
|
|
|
|
names: [],
|
|
|
|
};
|
2024-11-18 19:20:23 +00:00
|
|
|
export const actionRateLogger: Middleware = () => next => _action => {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const action = _action as any as UnknownAction;
|
2024-08-29 13:30:27 +00:00
|
|
|
const name = action.type;
|
|
|
|
const lastTimestamp = actionStats.timestamp;
|
|
|
|
let count = actionStats.names.length;
|
|
|
|
|
|
|
|
if (isOlderThan(lastTimestamp, SECOND)) {
|
|
|
|
if (count > 0) {
|
|
|
|
actionStats.names = [];
|
|
|
|
}
|
|
|
|
actionStats.timestamp = Date.now();
|
|
|
|
|
|
|
|
return next(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
actionStats.names.push(name);
|
|
|
|
count += 1;
|
|
|
|
|
|
|
|
if (count >= ACTION_COUNT_THRESHOLD) {
|
|
|
|
log.warn(
|
|
|
|
`ActionRateLogger: got ${count} events since ${lastTimestamp}: ${actionStats.names.join(',')}`
|
|
|
|
);
|
|
|
|
|
|
|
|
actionStats.names = [];
|
|
|
|
actionStats.timestamp = Date.now();
|
|
|
|
}
|
|
|
|
|
|
|
|
return next(action);
|
|
|
|
};
|
|
|
|
|
2020-10-30 18:00:01 +00:00
|
|
|
const middlewareList = [
|
|
|
|
promise,
|
|
|
|
thunk,
|
2021-08-18 20:08:14 +00:00
|
|
|
dispatchItemsMiddleware,
|
2024-08-29 13:30:27 +00:00
|
|
|
actionRateLogger,
|
2020-10-30 18:00:01 +00:00
|
|
|
...(env === 'production' ? [] : [logger]),
|
|
|
|
];
|
2019-01-14 21:49:58 +00:00
|
|
|
|
2020-09-14 21:56:35 +00:00
|
|
|
const enhancer = applyMiddleware(...middlewareList);
|
2019-01-14 21:49:58 +00:00
|
|
|
|
2021-01-26 23:12:23 +00:00
|
|
|
export const createStore = (
|
2022-02-23 18:48:40 +00:00
|
|
|
initialState: Readonly<StateType>
|
2024-11-18 19:20:23 +00:00
|
|
|
): Store<StateType> =>
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
reduxCreateStore<any, any>(reducer, initialState, enhancer);
|