Friday 2 December 2022

Use multi-tenant capabilities of SAP Job Scheduling Service to schedule tenant-specific jobs to pull data from the S/4HANA system

In this blog, we will see how to schedule periodic jobs for each of the subscribing tenants to pull data periodically from the backend system and ensure data isolation for each tenant.

SAP Job Scheduling Service


SAP Job Scheduling service allows you to define and manage jobs that run once or on a recurring schedule. Use this runtime-agnostic service to schedule action endpoints in your application or long-running processes using Cloud Foundry tasks. Use REST APIs to schedule jobs, including long-running jobs asynchronously, and create multiple schedule formats for simple and complex recurring schedules. Manage jobs and tasks and manage schedules with a web-based user interface.

SAP S/4HANA System, SAP HANA Exam, SAP HANA Prep, SAP HANA Tutorial and Materials, SAP HANA Guides, SAP HANA Skills, SAP HANA Jobs

Implementation


We have admin-srv where the job scheduler is implemented. This microservice is responsible for Updating the application name to adapt to subscribing customers’ names and logos.

Creating a Job :

Admin Service offers API where we can pass the job frequency, it then processes it and defines the job.

const JobSchedulerClient = require('@sap/jobs-client');
const xsenv = require('@sap/xsenv');

const jobSchedulerCreds = xsenv.serviceCredentials({ tag: 'jobscheduler' });
const jwt = require('../utility/jwt');

const createJob = async (req, logger) => {
  try {
    const subdomain = req.authInfo.getSubdomain();
    const domain = `https://${subdomain}.${jobSchedulerCreds.uaa.uaadomain}`;
    const token = await jwt(domain, jobSchedulerCreds);
    const options = {
      baseURL: `${jobSchedulerCreds.url}`,
      token: token.accessToken,
    };
    const scheduler = new JobSchedulerClient.Scheduler(options);
// name field is where we are trying to generate a unique name for the job
    const myJob = {
      name: `${subdomain.split("-")[0] + new Date().getMilliseconds()}`,
      description: "cron job that calls HTTP endpoint",
      action: `${process.env.businessPartnerAPI}/api/v1/new/bp`,
// action: URL to the backend service which should be called periodically
      active: true,
      httpMethod: "GET",
      schedules: [
        {
          cron: `* * * * * */${req.query.time} 0`,
// cron: frequency of job
          description: `this schedule runs every ${req.query.time} minutes to fetch the tenant data and find new businesspartners`,
          active: true,
          startTime: {
            date: `${new Date().toISOString().split('T')[0]} 00:00 +0000`,
            format: "YYYY-MM-DD HH:mm Z",
          },
        },
      ],
    };
    const scJob = { job: myJob };

    return new Promise((resolve, reject) => {
      scheduler.createJob(scJob, (error, body) => {
        if (error) {
          logger.error('Error registering new job %s', error);
          return reject(error);
        }
        return resolve(body);
      });
    });
  } catch (schedulererr) {
    logger.error(schedulererr);
    throw new Error("Error While creating the job");
  }
};

Getting Scheduled Jobs

This method returns a list of scheduled jobs for tenants ensuring data isolation for each of tenant.

const getJob = async (req, logger) => {
  try {
    const subdomain = req.authInfo.getSubdomain();
    const domain = `https://${subdomain}.${jobSchedulerCreds.uaa.uaadomain}`;
    const token = await jwt(domain, jobSchedulerCreds);
    const options = {
      baseURL: `${jobSchedulerCreds.url}`,
      token: token.accessToken,
    };
    const scheduler = new JobSchedulerClient.Scheduler(options);
    const data = {};
    return new Promise((resolve, reject) => {
      scheduler.fetchAllJobs(data, (err, result) => {
        if (err) {
           logger.error('Error retrieving jobs: %s', err);
          return reject(err);
        }
        // Jobs retrieved successfully
        logger.info(result)
        return resolve(result);
      });
    });
    
  } catch (errr) {
    logger.error(errr);
    throw errr;
  }
};

Here’s how it looks from the Admin dashboard

SAP S/4HANA System, SAP HANA Exam, SAP HANA Prep, SAP HANA Tutorial and Materials, SAP HANA Guides, SAP HANA Skills, SAP HANA Jobs

Scheduled Jobs from the job scheduler dashboard:

SAP S/4HANA System, SAP HANA Exam, SAP HANA Prep, SAP HANA Tutorial and Materials, SAP HANA Guides, SAP HANA Skills, SAP HANA Jobs

Conclusion: Using re-use services like SAP Job scheduling service in a multitenant application helps in reducing the total cost of application ownership significantly. It is a powerful concept that makes the implementation easier.

No comments:

Post a Comment