Skip to content

Commit

Permalink
feat: daily event report of all of a user's node packages (#348)
Browse files Browse the repository at this point in the history
* Initial branch commit

* Step 1-6 implementation

* Event Listener & nodePackage fix

* cleanup cronjob into a file and add native cron dep to release/app

* fix: delete all nodes and data to clear detatched data

* fix: limit node data sent for daily report

---------

Co-authored-by: jgresham <[email protected]>
  • Loading branch information
Gathin23 and jgresham authored Oct 22, 2023
1 parent 390dcf1 commit 89f8cb4
Show file tree
Hide file tree
Showing 13 changed files with 210 additions and 10 deletions.
27 changes: 25 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@
"@vscode/sudo-prompt": "^9.3.1",
"await-sleep": "0.0.1",
"check-disk-space": "^3.3.1",
"cron": "^3.1.3",
"docker-cli-js": "^2.10.0",
"dotenv": "^16.0.3",
"du": "^1.0.0",
Expand Down
42 changes: 42 additions & 0 deletions release/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions release/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"license": "MIT",
"dependencies": {
"cron": "^3.1.3",
"dockerode": "^3.3.5",
"systeminformation": "^5.21.7"
}
Expand Down
5 changes: 4 additions & 1 deletion src/common/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export type NodeService = {
node: Node;
};
export type NodePackage = {
nodes: Node[];
id: NodeId;
services: NodeService[];
spec: NodePackageSpecification;
Expand All @@ -86,7 +87,8 @@ export type NodePackage = {
lastStarted?: string;
lastStopped?: string;
};
type NodePackageMap = Record<string, NodePackage>;
export type NodePackageMap = Record<string, NodePackage>;

export type UserNodePackages = {
nodes: NodePackageMap;
nodeIds: string[];
Expand Down Expand Up @@ -170,6 +172,7 @@ export const createNodePackage = (input: {
}

const nodePackage: NodePackage = {
nodes: [],
id: uuidv4(),
spec: input.spec,
services: [],
Expand Down
95 changes: 95 additions & 0 deletions src/main/cronJobs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { CronJob } from 'cron';
import logger from './logger';
import { reportEvent } from './events';
import { getUserNodePackagesWithNodes } from './state/nodePackages';
import store from './state/store';
import { NodeId, NodeStatus, UserNodePackages } from '../common/node';

const CRON_ONCE_A_DAY = '0 0 * * *';
// const CRON_ONCE_A_DAY = '* * * * *'; // one minute for testing

type NodeReportData = {
specId: string;
specVersion: string;
status: NodeStatus;
diskUsedGBs?: number;
};

type PackageReportData = {
specId: string;
specVersion: string;
status: NodeStatus;
nodes: Record<NodeId, NodeReportData>;
};
export const reportDataForNodePackages = (
userNodePackages: UserNodePackages,
) => {
const reportData: Record<NodeId, PackageReportData> = {};

userNodePackages?.nodeIds.forEach((nodeId: NodeId) => {
const nodePackage = userNodePackages.nodes[nodeId];
const packageReportData: PackageReportData = {
specId: nodePackage.spec.specId,
specVersion: nodePackage.spec.version,
status: nodePackage.status,
nodes: {},
};

nodePackage.nodes.forEach((node) => {
let diskUsedGBs;
if (node.runtime?.usage?.diskGBs?.[0]?.y !== undefined) {
diskUsedGBs = node.runtime.usage.diskGBs[0].y;
}
packageReportData.nodes[node.id] = {
specId: node.spec.specId,
specVersion: node.spec.version,
status: node.status,
diskUsedGBs,
};
});

reportData[nodeId] = packageReportData;
});
return reportData;
};

const dailyReportFunc = async () => {
const lastDailyReportTimestamp = store.get(
'lastDailyReportTimestamp',
) as number;
const nowTimestamp = Date.now();
// Subtracts 23 hours and 59 minutes ago, (86,340,000 milliseconds)
const oneDayAgo = nowTimestamp - 23 * 60 * 60 * 1000 - 59 * 60 * 1000;
// const oneDayAgo = nowTimestamp + 1 * 60 * 1000; // one minute for testing
if (
lastDailyReportTimestamp < oneDayAgo ||
lastDailyReportTimestamp === undefined
) {
// It's been more than a day, proceed with the report
logger.info(
'Cron dailyReportJob: it has been more than a day. Reporting dailyReport.',
);
const userNodePackages = await getUserNodePackagesWithNodes();
// console.log(
// 'userNodePackages: ',
// JSON.stringify(userNodePackages, null, 2),
// );
const reportData = reportDataForNodePackages(userNodePackages);
// console.log('reportData: ', JSON.stringify(reportData));
reportEvent('DailyUserReport', reportData);
store.set('lastDailyReportTimestamp', nowTimestamp);
}
};

// Run once everyday at midnight in the user's local timezone
const dailyReportJob = new CronJob(CRON_ONCE_A_DAY, async () => {
logger.info('Running cron dailyReportJob...');
await dailyReportFunc();
logger.info('End cron dailyReportJob.');
});

export const initialize = () => {
// Start the cron jobs and then run some for a first time now
dailyReportJob.start();
dailyReportFunc();
};
3 changes: 2 additions & 1 deletion src/main/events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ReportEventData } from 'renderer/events/reportEvent';
import { ReportEventData } from '../renderer/events/reportEvent';
import { CHANNELS, send } from './messenger';

export const reportEvent = (event: string, eventData?: ReportEventData) => {
// console.log('reportEvent: ', event, eventData);
send(CHANNELS.reportEvent, event, eventData);
};
3 changes: 2 additions & 1 deletion src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import path from 'path';
import { app, BrowserWindow, shell } from 'electron';
import * as Sentry from '@sentry/electron/main';

import logger from './logger';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
Expand All @@ -28,6 +27,7 @@ import * as systemInfo from './systemInfo';
import { setCorsForNiceNode } from './corsMiddleware';
import * as updater from './updater';
import * as monitor from './monitor';
import * as cronJobs from './cronJobs';

if (process.env.NODE_ENV === 'development') {
require('dotenv').config();
Expand Down Expand Up @@ -180,6 +180,7 @@ const initialize = () => {
processExit.initialize();
processExit.registerExitHandler(onExit);
monitor.initialize();
cronJobs.initialize();
console.log('app locale: ', app.getLocale());
console.log('app LocaleCountryCode: ', app.getLocaleCountryCode());
};
Expand Down
5 changes: 5 additions & 0 deletions src/main/nodePackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Node, {
NodeStatus,
} from '../common/node';
import * as nodePackageStore from './state/nodePackages';
import * as nodeStore from './state/nodes';
import {
deleteDisk,
getNodeSpecificationsFolder,
Expand Down Expand Up @@ -240,4 +241,8 @@ export const removeAllNodePackages = async () => {
const node = nodes[i];
await removeNodePackage(node.id, { isDeleteStorage: true });
}

// Useful if the data in the store is stored/deleted improperly
nodePackageStore.clear();
nodeStore.clear();
};
23 changes: 23 additions & 0 deletions src/main/state/nodePackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Node, {
} from '../../common/node';
import store from './store';
import { ConfigValuesMap } from '../../common/nodeConfig';
import { getUserNodes } from './nodes';

export const USER_NODE_PACKAGES_KEY = 'userNodePackages';
const NODES_KEY = 'nodes';
Expand Down Expand Up @@ -47,6 +48,10 @@ const initialize = () => {
};
initialize();

export const clear = () => {
store.set(USER_NODE_PACKAGES_KEY, { [NODES_KEY]: {}, [NODE_IDS_KEY]: [] });
};

export const getUserNodePackages = (): UserNodePackages => {
const userNodePackages: UserNodePackages = store.get(USER_NODE_PACKAGES_KEY);
return userNodePackages;
Expand Down Expand Up @@ -172,3 +177,21 @@ export const removeNodePackage = (nodeId: NodeId) => {
store.set(USER_NODE_PACKAGES_KEY, { nodes, nodeIds: newNodeIds });
return nodeToRemove;
};

export const getUserNodePackagesWithNodes = async () => {
const userNodePackages = await getUserNodePackages();
const userNodes = await getUserNodes();

userNodePackages?.nodeIds.forEach((nodeId: NodeId) => {
const nodePackage = userNodePackages.nodes[nodeId];
const nodes: Node[] = [];

nodePackage.services.forEach((service) => {
const nodeId: NodeId = service.node.id;
const node = userNodes?.nodes[nodeId];
nodes.push(node);
});
nodePackage.nodes = nodes;
});
return userNodePackages;
};
4 changes: 4 additions & 0 deletions src/main/state/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const initialize = () => {
};
initialize();

export const clear = () => {
store.set(USER_NODES_KEY, { [NODES_KEY]: {}, [NODE_IDS_KEY]: [] });
};

export const getUserNodes = (): UserNodes => {
const userNodes: UserNodes = store.get(USER_NODES_KEY);
return userNodes;
Expand Down
Loading

0 comments on commit 89f8cb4

Please sign in to comment.