0

I am attempting to create a scheduled function in google cloud which starts from an event sent from a cloud function trigger, runs for a period of time, and then stops based on a condition or another event

Trigger -> Start scheduled function -> run on crontab schedule until condition met -> stop scheduled function

It looks like I can use Pubsub and EventARC to do this, by creating a scheduled function which is subscribed to a topic within Pubsub and then start and stop the function based on the messages sent.

Can anyone point me towards an example project or some documentation which describes this architecture in detail?

Implicitly publish message to topic from Cloud trigger:

const messageId = await pubSubClient
  .topic(
    `my_topic_name`
  )
  .publishMessage({ data });

enter image description here

Jeff Voss
  • 3,637
  • 8
  • 46
  • 71

1 Answers1

1

The following code will produce the desired result:

It uses Cloud Scheduler to create a scheduled job on the fly and then cancels the job once a certain condition is met

const { CloudSchedulerClient } = require('@google-cloud/scheduler');
const { CloudFunctionsServiceClient } = require('@google-cloud/functions');

exports.delayed_scheduled_function = async (data, context) => {
  // This function will be triggered by the Scheduler
  // and will execute after the delay time has passed
  console.log('Scheduled function has been triggered!');
  console.log(`Triggered by ${context.resource}`);

  // Check the condition
  if (condition_met) {
    console.log('Condition met. Cancelling scheduled function...');
    // Cancel the scheduled function by deleting the Cloud Scheduler job
    const schedulerClient = new CloudSchedulerClient();
    const jobName = 'delayed-scheduled-function-job';
    const jobPath = schedulerClient.jobPath(
      process.env.GOOGLE_CLOUD_PROJECT,
      process.env.GOOGLE_CLOUD_SCHEDULER_LOCATION,
      jobName
    );
    await schedulerClient.deleteJob({ name: jobPath });
    console.log(`Job ${jobName} has been cancelled.`);
  }
};

exports.onCreateTrigger = async (data, context) => {
  // Get the current time and calculate the delay time
  const current_time = new Date();
  const delay_time = new Date(current_time.getTime() + (5 * 60 * 1000)); // Delay execution for 5 minutes

  // Create a Cloud Scheduler client and define the job
  const schedulerClient = new CloudSchedulerClient();
  const parent = schedulerClient.locationPath(
    process.env.GOOGLE_CLOUD_PROJECT,
    process.env.GOOGLE_CLOUD_SCHEDULER_LOCATION
  );
  const job = {
    name: 'delayed-scheduled-function-job',
    schedule: '*/30 6-17 * * 1-5',
    timeZone: 'America/Los_Angeles',
    httpTarget: {
      uri: process.env.CLOUD_FUNCTION_URL,
      httpMethod: 'POST',
      body: Buffer.from('').toString('base64'),
    },
    retryConfig: {
      retryCount: 5,
      maxRetryDuration: { seconds: 600 },
      minBackoffDuration: { seconds: 10 },
      maxBackoffDuration: { seconds: 30 },
    },
    pubsubTarget: {},
    updateTime: {},
    state: 'ENABLED',
    userUpdateTime: {},
  };

  // Create the job and wait for the delay time to pass
  const [jobResponse] = await schedulerClient.createJob({
    parent,
    job,
  });
  console.log(`Job created: ${jobResponse.name}`);

  const executionTime = delay_time.toISOString();
  console.log(`Waiting until ${executionTime} to trigger the function...`);
  await new Promise((resolve) => setTimeout(resolve, delay_time - current_time));

  // Create a Cloud Functions client and execute the function
  const functionsClient = new CloudFunctionsServiceClient();
  const [operation] = await functionsClient.callFunction({
    name: process.env.CLOUD_FUNCTION_NAME,
    data: '',
  });
  const response = await operation.promise();
  console.log(`Function executed: ${response.result}`);
};
Jeff Voss
  • 3,637
  • 8
  • 46
  • 71