This is full code of Cloud Functions of this blogpost : Schedule Cloud Functions with Cloud Tasks (for Document TTL) Part 1
Last active
June 25, 2023 07:07
-
-
Save AdnanKhan45/16ffa5d8d49cdf064da4469c05dd2e40 to your computer and use it in GitHub Desktop.
Schedule Cloud Functions with Cloud Tasks (for Document TTL) Part 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as functions from 'firebase-functions' | |
import * as admin from 'firebase-admin' | |
const { CloudTasksClient } = require('@google-cloud/tasks') | |
import { OAuth2Client } from “google-auth-library”; | |
admin.initializeApp() | |
export const onCreateEvent = functions.firestore.document("/events/${eventId}").onCreate(async snapshot => { | |
const data = snapshot.data() as { expireSeconds: number, expireTime: admin.firestore.timestamp }; | |
const { expireSeconds, expireTime } = data; | |
// This is local variable for storing expirationAtSeconds | |
let expirationAtSeconds: number | undefined | |
// Extract expiration time based on provided fields | |
if(expireSeconds) { | |
if(expireSeconds > 0) { | |
expirationAtSeconds = Date.now() / 100 + expireSeconds; | |
} | |
} else if (expireTime) { | |
expirationAtSeconds = expireTime.seconds; | |
} | |
// If not time is set for the document we will return | |
if(expirationAtSeconds == undefined) { | |
return; | |
} | |
const project = json.parse(process.env.FIREBASE_CONFIG!).projectId; | |
const location = ‘us-central1’; | |
const queue = ‘my-scheduler’; | |
const taskClient = new CloudTaskClient(); | |
const queuePath: string = taskClient.queuePath(project, location, queue); | |
const serviceAccountEmail = “SERVICE_ACCOUNT_EMAIL_HERE”; | |
const url = `https://${location}-${project}.cloudfunctions.net/schedulerCallback?eventId=${snapshot.id}`; | |
const payload = { snapshot.id }; | |
const taskName = ‘projects/${project}/locations/${location}/queues/${queue}/tasks’ | |
const task = { | |
name: `${taskName}/myTask-${snapshot.id}-${expireSeconds}`, | |
httpRequest: { | |
httpMethod: ‘POST’, | |
url: url, | |
body: Buffer.from(JSON.stringify(payload)).toString(‘base64’), | |
headers: { ‘Content-Type’: ‘application/json’ } | |
}, | |
oidcToken: { | |
serviceAccountEmail, | |
audience: “https://${location}-${project}.cloudfunctions.net/schedulerCallback” | |
}, | |
scheduleTime: { | |
seconds: expirationAtSeconds | |
} | |
} | |
await tasksClient.createTask({ parent: queuePath, task }) | |
}); | |
export const schedulerCallback = functions.https.onRequest(async (req, res) => { | |
const project = json.parse(process.env.FIREBASE_CONFIG!).projectId; | |
const location = ‘us-central1’; | |
const eventId = req.query.eventId as string; | |
// access the headers > authorization of the request | |
const authorizationHeader = req.headers.authorization; | |
// check if authorization header is not null | |
if(!authorizationHeader) { | |
res.status(401).send(“unauthorized token”); | |
return; | |
} | |
// if authorizationHeader is not null access the token | |
const token = authorizationHeader.split(‘ ’)[1]; | |
// verify ID token | |
try { | |
await verifyIdToken(token, location, project); | |
} catch (error) { | |
console.log(error); | |
res.status(401).send(“Unauthorized token”); | |
return; | |
} | |
// delete document | |
try { | |
await admin.firestore().collection(“events”).doc(eventId).delete(); | |
} catch(e) { | |
console.log(e); | |
res.status(500).send(e); | |
} | |
}); | |
async function verifyIdToken(token: string, location: any, project: any) { | |
const client = new OAuth2Client(); | |
const ticket = await client.verifyIdToken({ | |
idToken: token, | |
audience: “https://${location}-${project}.cloudfunctions.net/schedulerCallback”, | |
}); | |
return ticket.getPayload(); | |
} | |
export const onUpdateEventCancel functions.firestore.document(“/events/{eventId}”).onUpdate(async change => { | |
const eventBeforeUpdate = change.before.data(); | |
const eventAfterUpdate = change.after.data(); | |
// check if event is canceled | |
if(eventBeforeUpdate.expirationStatus !== eventAfterUpdate.eventAfterUpdate && eventAfterUpdate.expirationStatus === ‘canceled’) { | |
const project = json.parse(process.env.FIREBASE_CONFIG!).projectId; | |
const location = ‘us-central1’; | |
const queue = ‘my-scheduler’; | |
const taskClient = new CloudTasksClient(); | |
// task details | |
const eventId = eventAfterUpdate.eventId; | |
const expireSeconds = eventAfterUpdate.expireSeconds; | |
// taskName | |
const taskName = ‘projects/${project}/locations/${location}/queues/${queue}/tasks/myTask-${eventId}-${expireSeconds}’; | |
await taskClient.deleteTask({ name: taskName }); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment