firestore-queue
Version:
A powerful, scalable queue system built on Google Firestore with time-based indexing, auto-configuration, and connection reuse
309 lines (292 loc) • 8.87 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CloudFunctionWriter = void 0;
const FirestoreWriter_1 = require("./FirestoreWriter");
/**
* Cloud Function Writer for Fire Queue
* Integrates with Google Cloud Functions for automatic queue writing
*/
class CloudFunctionWriter {
constructor(config) {
this.config = {
region: 'us-central1',
triggerType: 'firestore',
...config,
};
// Use FirestoreWriter as the underlying writer
this.firestoreWriter = new FirestoreWriter_1.FirestoreWriter(config);
}
/**
* Write message (delegates to FirestoreWriter)
*/
async write(message) {
return this.firestoreWriter.write(message);
}
/**
* Write batch (delegates to FirestoreWriter)
*/
async writeBatch(messages) {
return this.firestoreWriter.writeBatch(messages);
}
/**
* Generate Cloud Function code for automatic queue writing
*/
generateCloudFunction() {
switch (this.config.triggerType) {
case 'firestore':
return this.generateFirestoreTrigger();
case 'http':
return this.generateHTTPTrigger();
case 'schedule':
return this.generateScheduleTrigger();
default:
throw new Error(`Unsupported trigger type: ${this.config.triggerType}`);
}
}
/**
* Generate Firestore trigger function
*/
generateFirestoreTrigger() {
return `
import { onDocumentWritten } from 'firebase-functions/v2/firestore';
import { FirestoreWriter } from 'fire-queue';
const queueWriter = new FirestoreWriter({
queueName: '${this.config.queueName}',
projectId: '${this.config.projectId}',
databaseId: '${this.config.databaseId || '(default)'}',
enableBatching: true,
batchSize: 50,
batchTimeoutMs: 30000, // 30 seconds
});
/**
* Auto-generated Fire Queue writer function
* Triggers on Firestore document changes and queues them for processing
*/
export const queueDocumentChanges = onDocumentWritten({
document: '{collection}/{docId}', // Configure your document path
region: '${this.config.region}',
}, async (event) => {
const change = event.data;
const docId = event.params.docId;
if (!change) return;
try {
// Determine operation type
let operation: 'CREATE' | 'UPDATE' | 'DELETE';
let data: any;
if (!change.before?.exists && change.after?.exists) {
operation = 'CREATE';
data = change.after.data();
} else if (change.before?.exists && !change.after?.exists) {
operation = 'DELETE';
data = change.before.data();
} else {
operation = 'UPDATE';
data = change.after?.data();
}
// Queue the change
await queueWriter.write({
type: 'document_change',
payload: {
docId,
operation,
data,
collection: event.params.collection || 'unknown',
},
priority: operation === 'DELETE' ? 1 : 3,
tags: [operation.toLowerCase(), 'auto-generated'],
metadata: {
source: 'firestore-trigger',
functionName: '${this.config.functionName}',
timestamp: new Date().toISOString(),
},
});
console.log(\`Queued \${operation} for document \${docId}\`);
} catch (error) {
console.error('Failed to queue document change:', error);
}
});
`;
}
/**
* Generate HTTP trigger function
*/
generateHTTPTrigger() {
return `
import { onRequest } from 'firebase-functions/v2/https';
import { FirestoreWriter } from 'fire-queue';
const queueWriter = new FirestoreWriter({
queueName: '${this.config.queueName}',
projectId: '${this.config.projectId}',
databaseId: '${this.config.databaseId || '(default)'}',
validatePayload: true,
maxPayloadSize: 1024 * 1024, // 1MB
});
/**
* Auto-generated Fire Queue HTTP writer function
* Accepts HTTP requests and queues them for processing
*/
export const queueHTTPRequests = onRequest({
region: '${this.config.region}',
cors: true,
}, async (req, res) => {
// Only allow POST requests
if (req.method !== 'POST') {
res.status(405).json({ error: 'Method not allowed' });
return;
}
try {
const { message, messages } = req.body;
if (message) {
// Single message
const result = await queueWriter.write({
...message,
metadata: {
...message.metadata,
source: 'http-trigger',
userAgent: req.get('User-Agent'),
ip: req.ip,
timestamp: new Date().toISOString(),
},
});
res.json(result);
} else if (messages && Array.isArray(messages)) {
// Batch messages
const result = await queueWriter.writeBatch(
messages.map(msg => ({
...msg,
metadata: {
...msg.metadata,
source: 'http-trigger',
userAgent: req.get('User-Agent'),
ip: req.ip,
timestamp: new Date().toISOString(),
},
}))
);
res.json(result);
} else {
res.status(400).json({
error: 'Either message or messages array is required'
});
}
} catch (error) {
console.error('HTTP queue write failed:', error);
res.status(500).json({
error: error.message
});
}
});
`;
}
/**
* Generate scheduled trigger function
*/
generateScheduleTrigger() {
return `
import { onSchedule } from 'firebase-functions/v2/scheduler';
import { FirestoreWriter } from 'fire-queue';
const queueWriter = new FirestoreWriter({
queueName: '${this.config.queueName}',
projectId: '${this.config.projectId}',
databaseId: '${this.config.databaseId || '(default)'}',
enableBatching: true,
batchSize: 100,
});
/**
* Auto-generated Fire Queue scheduled writer function
* Runs on schedule and queues periodic tasks
*/
export const queueScheduledTasks = onSchedule({
schedule: '${this.config.schedule || 'every 5 minutes'}',
region: '${this.config.region}',
}, async () => {
console.log('Scheduled queue writer triggered');
try {
// Example: Queue periodic maintenance tasks
const tasks = [
{
type: 'maintenance',
payload: {
task: 'cleanup_expired_data',
schedule: '${this.config.schedule}',
},
priority: 5,
tags: ['maintenance', 'scheduled'],
},
{
type: 'health_check',
payload: {
task: 'system_health_check',
timestamp: Date.now(),
},
priority: 3,
tags: ['health', 'monitoring'],
},
];
const result = await queueWriter.writeBatch(tasks);
console.log(\`Queued \${result.successfulWrites} scheduled tasks\`);
} catch (error) {
console.error('Scheduled queue write failed:', error);
}
});
`;
}
/**
* Generate deployment configuration
*/
generateDeploymentConfig() {
return {
functions: {
[this.config.functionName]: {
source: './functions',
runtime: 'nodejs18',
region: this.config.region,
environmentVariables: {
FIRE_QUEUE_PROJECT_ID: this.config.projectId,
FIRE_QUEUE_NAME: this.config.queueName,
FIRE_QUEUE_DATABASE_ID: this.config.databaseId || '(default)',
},
...(this.config.triggerType === 'schedule' && {
schedule: this.config.schedule,
}),
},
},
};
}
/**
* Generate package.json for Cloud Function
*/
generatePackageJson() {
return {
name: `fire-queue-${this.config.functionName}`,
version: '1.0.0',
description: `Auto-generated Fire Queue writer function: ${this.config.functionName}`,
main: 'lib/index.js',
scripts: {
build: 'tsc',
deploy: 'npm run build && firebase deploy --only functions',
serve: 'npm run build && firebase emulators:start --only functions',
},
dependencies: {
'firebase-functions': '^4.0.0',
'firebase-admin': '^12.0.0',
'fire-queue': '^0.1.0',
},
devDependencies: {
typescript: '^5.0.0',
'@types/node': '^20.0.0',
},
engines: {
node: '18',
},
};
}
/**
* Close writer
*/
async close() {
await this.firestoreWriter.close();
}
}
exports.CloudFunctionWriter = CloudFunctionWriter;
//# sourceMappingURL=CloudFunctionWriter.js.map