Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 56 additions & 33 deletions github-metrics/check-last-run.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,43 @@
import fs from 'fs';
import { writeFile, mkdir } from 'fs/promises';
import path from 'path';

// Path to the state file (mounted from persistent volume)
// Can be overridden via STATE_FILE_PATH environment variable
const STATE_FILE_PATH = process.env.STATE_FILE_PATH || '/data/last-run.json';
import { MongoClient } from 'mongodb';

// Minimum days between runs (13 days to account for timing variations with weekly Monday runs)
// Can be overridden via MIN_DAYS_BETWEEN_RUNS environment variable
const MIN_DAYS_BETWEEN_RUNS = parseInt(process.env.MIN_DAYS_BETWEEN_RUNS || '13', 10);

// State document identifier
const STATE_DOC_ID = 'last-run-state';

/**
* Get the MongoDB collection for storing state
* @param {MongoClient} client - MongoDB client
* @returns {Collection} The state collection
*/
function getStateCollection(client) {
const database = client.db('github_metrics');
return database.collection('job_state');
}

/**
* Check if enough time has passed since the last run
* @returns {boolean} true if should run, false if should skip
* @returns {Promise<boolean>} true if should run, false if should skip
*/
export function shouldRun() {
export async function shouldRun() {
const uri = process.env.ATLAS_CONNECTION_STRING;
const client = new MongoClient(uri);

try {
// Check if state file exists
if (!fs.existsSync(STATE_FILE_PATH)) {
await client.connect();
const collection = getStateCollection(client);

// Find the last run state document
const stateDoc = await collection.findOne({ _id: STATE_DOC_ID });

if (!stateDoc) {
console.log('No previous run found. Running for the first time.');
return true;
}

// Read the last run timestamp
const stateData = JSON.parse(fs.readFileSync(STATE_FILE_PATH, 'utf8'));
const lastRunTime = new Date(stateData.lastRun);
const lastRunTime = new Date(stateDoc.lastRun);
const now = new Date();

// Calculate days since last run
Expand All @@ -35,44 +48,54 @@ export function shouldRun() {
console.log(`Minimum days required: ${MIN_DAYS_BETWEEN_RUNS}`);

if (daysSinceLastRun < MIN_DAYS_BETWEEN_RUNS) {
console.log(`⏭️ Skipping run - only ${daysSinceLastRun.toFixed(2)} days since last run (need ${MIN_DAYS_BETWEEN_RUNS})`);
console.log(`Skipping run - only ${daysSinceLastRun.toFixed(2)} days since last run (need ${MIN_DAYS_BETWEEN_RUNS})`);
return false;
}

console.log(`Proceeding with run - ${daysSinceLastRun.toFixed(2)} days since last run`);
console.log(`Proceeding with run - ${daysSinceLastRun.toFixed(2)} days since last run`);
return true;

} catch (error) {
console.error('Error checking last run time:', error.message);
console.log('Proceeding with run due to error reading state file');
return true; // Run if we can't read the state file
console.log('Proceeding with run due to error reading state from database');
return true; // Run if we can't read the state
} finally {
await client.close();
}
}

/**
* Update the state file with the current timestamp
* Update the state in MongoDB with the current timestamp
*/
export async function updateLastRun() {
const uri = process.env.ATLAS_CONNECTION_STRING;
const client = new MongoClient(uri);

try {
await client.connect();
const collection = getStateCollection(client);
const now = new Date();
const stateData = {
lastRun: now.toISOString(),
timestamp: now.getTime()
};

// Ensure the directory exists
const dir = path.dirname(STATE_FILE_PATH);
if (!fs.existsSync(dir)) {
await mkdir(dir, { recursive: true });
}

// Write the state file
await writeFile(STATE_FILE_PATH, JSON.stringify(stateData, null, 2), 'utf8');
console.log(`✅ Updated last run timestamp: ${now.toISOString()}`);
// Upsert the state document
await collection.updateOne(
{ _id: STATE_DOC_ID },
{
$set: {
lastRun: now.toISOString(),
timestamp: now.getTime(),
updatedAt: now
}
},
{ upsert: true }
);

console.log(`Updated last run timestamp in database: ${now.toISOString()}`);

} catch (error) {
console.error('Error updating last run time:', error.message);
// Don't throw - we don't want to fail the job just because we can't write the state file
// Don't throw - we don't want to fail the job just because we can't write the state
} finally {
await client.close();
}
}

Expand Down
9 changes: 1 addition & 8 deletions github-metrics/cronjobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,4 @@ cronJobs:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
# Persistent volume to store last run timestamp
persistence:
enabled: true
name: github-metrics-state
storageClass: "kops-csi-1-21"
accessMode: ReadWriteOnce
size: 1Gi
mountPath: /data
# Last run state is now stored in MongoDB instead of a PVC
2 changes: 1 addition & 1 deletion github-metrics/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async function main() {

try {
// Check if enough time has passed since last run
if (!shouldRun()) {
if (!await shouldRun()) {
console.log('Exiting - not enough time has passed since last run');
await sendSlackNotification({ skipped: true });
process.exit(0);
Expand Down