github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/redux/apiReducers.ts (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import _ from "lodash"; 12 import { combineReducers } from "redux"; 13 import moment from "moment"; 14 15 import { 16 CachedDataReducer, 17 CachedDataReducerState, 18 KeyedCachedDataReducer, 19 KeyedCachedDataReducerState, 20 } from "./cachedDataReducer"; 21 import * as api from "src/util/api"; 22 import { VersionList } from "src/interfaces/cockroachlabs"; 23 import { versionCheck } from "src/util/cockroachlabsAPI"; 24 import { INodeStatus, RollupStoreMetrics } from "src/util/proto"; 25 import * as protos from "src/js/protos"; 26 27 // The primary export of this file are the "refresh" functions of the various 28 // reducers, which are used by many react components to request fresh data. 29 // However, some of the reducer objects are also fully exported for use 30 // in tests. 31 32 export const clusterReducerObj = new CachedDataReducer( 33 api.getCluster, 34 "cluster", 35 ); 36 export const refreshCluster = clusterReducerObj.refresh; 37 38 const eventsReducerObj = new CachedDataReducer( 39 api.getEvents, 40 "events", 41 moment.duration(10, "s"), 42 ); 43 export const refreshEvents = eventsReducerObj.refresh; 44 45 export type HealthState = CachedDataReducerState<api.HealthResponseMessage>; 46 export const healthReducerObj = new CachedDataReducer( 47 api.getHealth, 48 "health", 49 moment.duration(2, "s"), 50 ); 51 export const refreshHealth = healthReducerObj.refresh; 52 53 function rollupStoreMetrics( 54 res: api.NodesResponseMessage, 55 ): INodeStatus[] { 56 return _.map(res.nodes, node => { 57 RollupStoreMetrics(node); 58 return node; 59 }); 60 } 61 62 export const nodesReducerObj = new CachedDataReducer( 63 (req: api.NodesRequestMessage, timeout?: moment.Duration) => 64 api.getNodes(req, timeout).then(rollupStoreMetrics), 65 "nodes", 66 moment.duration(10, "s"), 67 ); 68 export const refreshNodes = nodesReducerObj.refresh; 69 70 const raftReducerObj = new CachedDataReducer( 71 api.raftDebug, 72 "raft", 73 moment.duration(10, "s"), 74 ); 75 export const refreshRaft = raftReducerObj.refresh; 76 77 export const versionReducerObj = new CachedDataReducer(versionCheck, "version"); 78 export const refreshVersion = versionReducerObj.refresh; 79 80 export const locationsReducerObj = new CachedDataReducer(api.getLocations, "locations", moment.duration(10, "m")); 81 export const refreshLocations = locationsReducerObj.refresh; 82 83 const databasesReducerObj = new CachedDataReducer( 84 api.getDatabaseList, 85 "databases", 86 ); 87 export const refreshDatabases = databasesReducerObj.refresh; 88 89 export const databaseRequestToID = ( 90 req: api.DatabaseDetailsRequestMessage, 91 ): string => req.database; 92 93 const databaseDetailsReducerObj = new KeyedCachedDataReducer( 94 api.getDatabaseDetails, 95 "databaseDetails", 96 databaseRequestToID, 97 ); 98 export const refreshDatabaseDetails = databaseDetailsReducerObj.refresh; 99 100 // NOTE: We encode the db and table name so we can combine them as a string. 101 // TODO(maxlang): there's probably a nicer way to do this 102 export function generateTableID(db: string, table: string) { 103 return `${encodeURIComponent(db)}/${encodeURIComponent(table)}`; 104 } 105 106 export const tableRequestToID = ( 107 req: api.TableDetailsRequestMessage | api.TableStatsRequestMessage, 108 ): string => generateTableID(req.database, req.table); 109 110 const tableDetailsReducerObj = new KeyedCachedDataReducer( 111 api.getTableDetails, 112 "tableDetails", 113 tableRequestToID, 114 ); 115 export const refreshTableDetails = tableDetailsReducerObj.refresh; 116 117 const tableStatsReducerObj = new KeyedCachedDataReducer( 118 api.getTableStats, 119 "tableStats", 120 tableRequestToID, 121 ); 122 export const refreshTableStats = tableStatsReducerObj.refresh; 123 124 const nonTableStatsReducerObj = new CachedDataReducer( 125 api.getNonTableStats, "nonTableStats", moment.duration(1, "m"), 126 ); 127 export const refreshNonTableStats = nonTableStatsReducerObj.refresh; 128 129 const logsReducerObj = new CachedDataReducer( 130 api.getLogs, 131 "logs", 132 moment.duration(10, "s"), 133 ); 134 export const refreshLogs = logsReducerObj.refresh; 135 136 export const livenessReducerObj = new CachedDataReducer( 137 api.getLiveness, 138 "liveness", 139 moment.duration(10, "s"), 140 ); 141 export const refreshLiveness = livenessReducerObj.refresh; 142 143 export const jobsKey = (status: string, type: protos.cockroach.sql.jobs.jobspb.Type, limit: number) => 144 `${encodeURIComponent(status)}/${encodeURIComponent(type.toString())}/${encodeURIComponent(limit.toString())}`; 145 146 const jobsRequestKey = (req: api.JobsRequestMessage): string => 147 jobsKey(req.status, req.type, req.limit); 148 149 const jobsReducerObj = new KeyedCachedDataReducer( 150 api.getJobs, 151 "jobs", 152 jobsRequestKey, 153 moment.duration(10, "s"), 154 ); 155 export const refreshJobs = jobsReducerObj.refresh; 156 157 export const queryToID = (req: api.QueryPlanRequestMessage): string => req.query; 158 159 const queryPlanReducerObj = new CachedDataReducer(api.getQueryPlan, "queryPlan"); 160 export const refreshQueryPlan = queryPlanReducerObj.refresh; 161 162 export const problemRangesRequestKey = (req: api.ProblemRangesRequestMessage): string => 163 _.isEmpty(req.node_id) ? "all" : req.node_id; 164 165 const problemRangesReducerObj = new KeyedCachedDataReducer( 166 api.getProblemRanges, 167 "problemRanges", 168 problemRangesRequestKey, 169 moment.duration(0), 170 moment.duration(1, "m"), 171 ); 172 export const refreshProblemRanges = problemRangesReducerObj.refresh; 173 174 export const certificatesRequestKey = (req: api.CertificatesRequestMessage): string => 175 _.isEmpty(req.node_id) ? "none" : req.node_id; 176 177 const certificatesReducerObj = new KeyedCachedDataReducer( 178 api.getCertificates, 179 "certificates", 180 certificatesRequestKey, 181 moment.duration(1, "m"), 182 ); 183 export const refreshCertificates = certificatesReducerObj.refresh; 184 185 export const rangeRequestKey = (req: api.RangeRequestMessage): string => 186 _.isNil(req.range_id) ? "none" : req.range_id.toString(); 187 188 const rangeReducerObj = new KeyedCachedDataReducer( 189 api.getRange, 190 "range", 191 rangeRequestKey, 192 moment.duration(0), 193 moment.duration(1, "m"), 194 ); 195 export const refreshRange = rangeReducerObj.refresh; 196 197 export const allocatorRangeRequestKey = (req: api.AllocatorRangeRequestMessage): string => 198 _.isNil(req.range_id) ? "none" : req.range_id.toString(); 199 200 const allocatorRangeReducerObj = new KeyedCachedDataReducer( 201 api.getAllocatorRange, 202 "allocatorRange", 203 allocatorRangeRequestKey, 204 moment.duration(0), 205 moment.duration(1, "m"), 206 ); 207 export const refreshAllocatorRange = allocatorRangeReducerObj.refresh; 208 209 export const rangeLogRequestKey = (req: api.RangeLogRequestMessage): string => 210 _.isNil(req.range_id) ? "none" : req.range_id.toString(); 211 212 const rangeLogReducerObj = new KeyedCachedDataReducer( 213 api.getRangeLog, 214 "rangeLog", 215 rangeLogRequestKey, 216 moment.duration(0), 217 moment.duration(5, "m"), 218 ); 219 export const refreshRangeLog = rangeLogReducerObj.refresh; 220 221 export const settingsReducerObj = new CachedDataReducer( 222 api.getSettings, 223 "settings", 224 moment.duration(0), 225 moment.duration(1, "m"), 226 ); 227 export const refreshSettings = settingsReducerObj.refresh; 228 229 export const storesRequestKey = (req: api.StoresRequestMessage): string => 230 _.isEmpty(req.node_id) ? "none" : req.node_id; 231 232 const storesReducerObj = new KeyedCachedDataReducer( 233 api.getStores, 234 "stores", 235 storesRequestKey, 236 moment.duration(0), 237 moment.duration(1, "m"), 238 ); 239 export const refreshStores = storesReducerObj.refresh; 240 241 const queriesReducerObj = new CachedDataReducer( 242 api.getStatements, 243 "statements", 244 moment.duration(5, "m"), 245 moment.duration(1, "m"), 246 ); 247 export const refreshStatements = queriesReducerObj.refresh; 248 249 const statementDiagnosticsReportsReducerObj = new CachedDataReducer( 250 api.getStatementDiagnosticsReports, 251 "statementDiagnosticsReports", 252 moment.duration(5, "m"), 253 moment.duration(1, "m"), 254 ); 255 export const refreshStatementDiagnosticsRequests = statementDiagnosticsReportsReducerObj.refresh; 256 export const invalidateStatementDiagnosticsRequests = statementDiagnosticsReportsReducerObj.invalidateData; 257 258 const dataDistributionReducerObj = new CachedDataReducer( 259 api.getDataDistribution, 260 "dataDistribution", 261 moment.duration(1, "m"), 262 ); 263 export const refreshDataDistribution = dataDistributionReducerObj.refresh; 264 265 const metricMetadataReducerObj = new CachedDataReducer(api.getAllMetricMetadata, "metricMetadata"); 266 export const refreshMetricMetadata = metricMetadataReducerObj.refresh; 267 268 export interface APIReducersState { 269 cluster: CachedDataReducerState<api.ClusterResponseMessage>; 270 events: CachedDataReducerState<api.EventsResponseMessage>; 271 health: HealthState; 272 nodes: CachedDataReducerState<INodeStatus[]>; 273 raft: CachedDataReducerState<api.RaftDebugResponseMessage>; 274 version: CachedDataReducerState<VersionList>; 275 locations: CachedDataReducerState<api.LocationsResponseMessage>; 276 databases: CachedDataReducerState<api.DatabasesResponseMessage>; 277 databaseDetails: KeyedCachedDataReducerState<api.DatabaseDetailsResponseMessage>; 278 tableDetails: KeyedCachedDataReducerState<api.TableDetailsResponseMessage>; 279 tableStats: KeyedCachedDataReducerState<api.TableStatsResponseMessage>; 280 nonTableStats: CachedDataReducerState<api.NonTableStatsResponseMessage>; 281 logs: CachedDataReducerState<api.LogEntriesResponseMessage>; 282 liveness: CachedDataReducerState<api.LivenessResponseMessage>; 283 jobs: KeyedCachedDataReducerState<api.JobsResponseMessage>; 284 queryPlan: CachedDataReducerState<api.QueryPlanResponseMessage>; 285 problemRanges: KeyedCachedDataReducerState<api.ProblemRangesResponseMessage>; 286 certificates: KeyedCachedDataReducerState<api.CertificatesResponseMessage>; 287 range: KeyedCachedDataReducerState<api.RangeResponseMessage>; 288 allocatorRange: KeyedCachedDataReducerState<api.AllocatorRangeResponseMessage>; 289 rangeLog: KeyedCachedDataReducerState<api.RangeLogResponseMessage>; 290 settings: CachedDataReducerState<api.SettingsResponseMessage>; 291 stores: KeyedCachedDataReducerState<api.StoresResponseMessage>; 292 statements: CachedDataReducerState<api.StatementsResponseMessage>; 293 dataDistribution: CachedDataReducerState<api.DataDistributionResponseMessage>; 294 metricMetadata: CachedDataReducerState<api.MetricMetadataResponseMessage>; 295 statementDiagnosticsReports: CachedDataReducerState<api.StatementDiagnosticsReportsResponseMessage>; 296 } 297 298 export const apiReducersReducer = combineReducers<APIReducersState>({ 299 [clusterReducerObj.actionNamespace]: clusterReducerObj.reducer, 300 [eventsReducerObj.actionNamespace]: eventsReducerObj.reducer, 301 [healthReducerObj.actionNamespace]: healthReducerObj.reducer, 302 [nodesReducerObj.actionNamespace]: nodesReducerObj.reducer, 303 [raftReducerObj.actionNamespace]: raftReducerObj.reducer, 304 [versionReducerObj.actionNamespace]: versionReducerObj.reducer, 305 [locationsReducerObj.actionNamespace]: locationsReducerObj.reducer, 306 [databasesReducerObj.actionNamespace]: databasesReducerObj.reducer, 307 [databaseDetailsReducerObj.actionNamespace]: databaseDetailsReducerObj.reducer, 308 [tableDetailsReducerObj.actionNamespace]: tableDetailsReducerObj.reducer, 309 [tableStatsReducerObj.actionNamespace]: tableStatsReducerObj.reducer, 310 [nonTableStatsReducerObj.actionNamespace]: nonTableStatsReducerObj.reducer, 311 [logsReducerObj.actionNamespace]: logsReducerObj.reducer, 312 [livenessReducerObj.actionNamespace]: livenessReducerObj.reducer, 313 [jobsReducerObj.actionNamespace]: jobsReducerObj.reducer, 314 [queryPlanReducerObj.actionNamespace]: queryPlanReducerObj.reducer, 315 [problemRangesReducerObj.actionNamespace]: problemRangesReducerObj.reducer, 316 [certificatesReducerObj.actionNamespace]: certificatesReducerObj.reducer, 317 [rangeReducerObj.actionNamespace]: rangeReducerObj.reducer, 318 [allocatorRangeReducerObj.actionNamespace]: allocatorRangeReducerObj.reducer, 319 [rangeLogReducerObj.actionNamespace]: rangeLogReducerObj.reducer, 320 [settingsReducerObj.actionNamespace]: settingsReducerObj.reducer, 321 [storesReducerObj.actionNamespace]: storesReducerObj.reducer, 322 [queriesReducerObj.actionNamespace]: queriesReducerObj.reducer, 323 [dataDistributionReducerObj.actionNamespace]: dataDistributionReducerObj.reducer, 324 [metricMetadataReducerObj.actionNamespace]: metricMetadataReducerObj.reducer, 325 [statementDiagnosticsReportsReducerObj.actionNamespace]: statementDiagnosticsReportsReducerObj.reducer, 326 }); 327 328 export { CachedDataReducerState, KeyedCachedDataReducerState };