chore(railway): update worker and add history migration script
This commit is contained in:
parent
b361463b9d
commit
a02827897c
|
|
@ -0,0 +1,105 @@
|
||||||
|
require('dotenv').config();
|
||||||
|
const admin = require('firebase-admin');
|
||||||
|
|
||||||
|
function inferSource(entry) {
|
||||||
|
const rawSource = (entry && entry.source ? String(entry.source) : '').trim().toLowerCase();
|
||||||
|
|
||||||
|
if (rawSource === 'server' || rawSource === 'worker') return 'server';
|
||||||
|
if (rawSource === 'app' || rawSource === 'mobile') return 'app';
|
||||||
|
|
||||||
|
const rawType = (entry && entry.type ? String(entry.type) : '').trim();
|
||||||
|
if (rawType.length > 0) return 'server';
|
||||||
|
|
||||||
|
return 'app';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const isDryRun = process.argv.includes('--dry-run');
|
||||||
|
|
||||||
|
const requiredEnvs = [
|
||||||
|
'FIREBASE_PROJECT_ID',
|
||||||
|
'FIREBASE_CLIENT_EMAIL',
|
||||||
|
'FIREBASE_PRIVATE_KEY',
|
||||||
|
'FIREBASE_DATABASE_URL',
|
||||||
|
];
|
||||||
|
|
||||||
|
const missing = requiredEnvs.filter((key) => !process.env[key]);
|
||||||
|
if (missing.length > 0) {
|
||||||
|
throw new Error(`Missing env vars: ${missing.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
admin.initializeApp({
|
||||||
|
credential: admin.credential.cert({
|
||||||
|
projectId: process.env.FIREBASE_PROJECT_ID,
|
||||||
|
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
|
||||||
|
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
|
||||||
|
}),
|
||||||
|
databaseURL: process.env.FIREBASE_DATABASE_URL,
|
||||||
|
});
|
||||||
|
|
||||||
|
const db = admin.database();
|
||||||
|
const snap = await db.ref('history').get();
|
||||||
|
|
||||||
|
if (!snap.exists()) {
|
||||||
|
console.log('No history node found. Nothing to migrate.');
|
||||||
|
await admin.app().delete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const history = snap.val();
|
||||||
|
const updates = {};
|
||||||
|
|
||||||
|
let totalEntries = 0;
|
||||||
|
let changedEntries = 0;
|
||||||
|
let serverAssigned = 0;
|
||||||
|
let appAssigned = 0;
|
||||||
|
|
||||||
|
for (const dateKey of Object.keys(history)) {
|
||||||
|
const dateNode = history[dateKey];
|
||||||
|
if (!dateNode || typeof dateNode !== 'object') continue;
|
||||||
|
|
||||||
|
for (const timeKey of Object.keys(dateNode)) {
|
||||||
|
const entry = dateNode[timeKey];
|
||||||
|
if (!entry || typeof entry !== 'object') continue;
|
||||||
|
|
||||||
|
totalEntries += 1;
|
||||||
|
const target = inferSource(entry);
|
||||||
|
const currentRaw = entry.source == null ? '' : String(entry.source).trim().toLowerCase();
|
||||||
|
const current = currentRaw === 'worker' ? 'server' : currentRaw === 'mobile' ? 'app' : currentRaw;
|
||||||
|
|
||||||
|
if (current !== target) {
|
||||||
|
updates[`history/${dateKey}/${timeKey}/source`] = target;
|
||||||
|
changedEntries += 1;
|
||||||
|
if (target === 'server') {
|
||||||
|
serverAssigned += 1;
|
||||||
|
} else {
|
||||||
|
appAssigned += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('=== History Source Migration ===');
|
||||||
|
console.log(`Mode: ${isDryRun ? 'DRY RUN' : 'APPLY'}`);
|
||||||
|
console.log(`Total entries scanned: ${totalEntries}`);
|
||||||
|
console.log(`Entries to update: ${changedEntries}`);
|
||||||
|
console.log(`Assign source=server: ${serverAssigned}`);
|
||||||
|
console.log(`Assign source=app: ${appAssigned}`);
|
||||||
|
|
||||||
|
if (!isDryRun && changedEntries > 0) {
|
||||||
|
await db.ref().update(updates);
|
||||||
|
console.log('Migration applied successfully.');
|
||||||
|
} else if (!isDryRun) {
|
||||||
|
console.log('No updates needed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await admin.app().delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(async (err) => {
|
||||||
|
console.error('Migration failed:', err.message);
|
||||||
|
process.exitCode = 1;
|
||||||
|
try {
|
||||||
|
await admin.app().delete();
|
||||||
|
} catch (_) {}
|
||||||
|
});
|
||||||
|
|
@ -1159,6 +1159,7 @@ async function logHistory(type, potNumbers, duration) {
|
||||||
|
|
||||||
await setFirebaseSmart(`history/${dateKey}/${timeKey}`, {
|
await setFirebaseSmart(`history/${dateKey}/${timeKey}`, {
|
||||||
timestamp: now.getTime(),
|
timestamp: now.getTime(),
|
||||||
|
source: 'server',
|
||||||
type: type,
|
type: type,
|
||||||
pots: potNumbers,
|
pots: potNumbers,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
|
|
@ -1185,6 +1186,7 @@ const autoLogJob = new cron.CronJob('*/30 * * * *', async () => {
|
||||||
|
|
||||||
await setFirebaseSmart(`history/${dateKey}/${timeKey}`, {
|
await setFirebaseSmart(`history/${dateKey}/${timeKey}`, {
|
||||||
timestamp: now.getTime(),
|
timestamp: now.getTime(),
|
||||||
|
source: 'server',
|
||||||
type: 'auto_log',
|
type: 'auto_log',
|
||||||
...sensorData,
|
...sensorData,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue