diff --git a/lib/clients/scheduler.doc.js b/lib/clients/scheduler.doc.js new file mode 100644 index 0000000..57b4233 --- /dev/null +++ b/lib/clients/scheduler.doc.js @@ -0,0 +1,60 @@ +/** + * AWS SchedulerClient client. + * @class SchedulerClient + * @see {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-eventbridge/index.html|@aws-sdk/client-scheduler} + * @param {Object} parameters + * @param {string} [parameters.name=scheduler] Client name. + * @param {string} [parameters.reqId=] Request id. + * @param {Object} [parameters.log=] Pino compatible logger. + * @param {Constructor} [parameters.AwsSdkSchedulerClient=SchedulerClient] + * Constructor for a SchedulerClient from the AWS SDK. + * @param {Object} [parameters.params={}] + * Additional params to pass to the AwsSdkSchedulerClient constructor. + */ + +/** + * Get a schedule. + * @async + * @function getSchedule + * @memberof SchedulerClient + * @instance + * @param {Object[]} [name] Name of the schedule to get. + * @param {Object} [params=[]] Additional params to pass to the GetScheduleCommand. + * @return {Promise} Response normalized to camel case. + */ + +/** + * Create a schedule. + * @async + * @function createSchedule + * @memberof SchedulerClient + * @instance + * @param {Object[]} [name] Name of the schedule to create. + * @param {Object} [params=[]] Additional params to pass to the CreateScheduleCommand. + * @return {Promise} Response normalized to camel case. + */ + +/** + * Delete a schedule. + * @async + * @function deleteSchedule + * @memberof SchedulerClient + * @instance + * @param {Object[]} [name] Name of the schedule to delete. + * @param {Object} [params=[]] Additional params to pass to the DeleteScheduleCommand. + * @return {Promise} Response normalized to camel case. + */ + +/** + * Update a schedule. + * AWS uses a replace all attributes strategy when updating schedules. + * This method simplifies updates by getting the existing schedule first and merging all existing top level keys with the new parameter values. + * AWS schedules + * @async + * @function deleteSchedule + * @memberof SchedulerClient + * @instance + * @param {Object[]} [name] Name of the schedule to update. + * @param {Object} [params=[]] Additional params to pass to the UpdateScheduleCommand. + * @return {Promise} Response normalized to camel case. + */ diff --git a/lib/clients/scheduler.js b/lib/clients/scheduler.js new file mode 100644 index 0000000..df8e0c9 --- /dev/null +++ b/lib/clients/scheduler.js @@ -0,0 +1,138 @@ +import { + SchedulerClient as AwsSdkSchedulerClient, + CreateScheduleCommand, + DeleteScheduleCommand, + GetScheduleCommand, + UpdateScheduleCommand +} from '@aws-sdk/client-scheduler' +import { v4 as uuidv4 } from 'uuid' +import { createLogger } from '@meltwater/mlabs-logger' + +import { createCache } from '../cache.js' +import { keysToCamelCase, keysToPascalCase } from '../case.js' + +const createClient = createCache() + +export class SchedulerClient { + #client + #reqId + #log + + constructor({ + name = 'scheduler', + reqId = uuidv4(), + log = createLogger(), + AwsEventBridgeClient = AwsSdkSchedulerClient, + params = {} + }) { + this.#client = createClient(name, () => new AwsEventBridgeClient(params)) + this.#reqId = reqId + this.#log = log.child({ + params, + client: name, + class: SchedulerClient.name, + reqId + }) + } + + async getSchedule(scheduleName, params = {}) { + const log = this.#log.child({ + scheduleName, + meta: params, + method: SchedulerClient.prototype.putEvents.name + }) + try { + log.info('start') + const req = formatReq({ name: scheduleName }) + const command = new GetScheduleCommand(req) + + const res = await this.#client.send(command) + + const data = formatRes(res) + + log.debug({ data }, 'data') + log.info('end') + return data + } catch (err) { + log.error({ err }, 'fail') + throw err + } + } + + async createSchedule(scheduleName, params = {}) { + const log = this.#log.child({ + scheduleName, + meta: params, + method: SchedulerClient.prototype.putEvents.name + }) + try { + log.info('start') + const req = formatReq({ ...params, name: scheduleName }) + const command = new CreateScheduleCommand(req) + + const res = await this.#client.send(command) + + const data = formatRes(res) + + log.debug({ data }, 'data') + log.info('end') + return data + } catch (err) { + log.error({ err }, 'fail') + throw err + } + } + + async deleteSchedule(scheduleName, params = {}) { + const log = this.#log.child({ + scheduleName, + meta: params, + method: SchedulerClient.prototype.putEvents.name + }) + try { + log.info('start') + const req = formatReq({ name: scheduleName }) + const command = new DeleteScheduleCommand(req) + + const res = await this.#client.send(command) + + const data = formatRes(res) + + log.debug({ data }, 'data') + log.info('end') + return data + } catch (err) { + log.error({ err }, 'fail') + throw err + } + } + + async updateSchedule(scheduleName, params = {}) { + const log = this.#log.child({ + scheduleName, + meta: params, + method: SchedulerClient.prototype.putEvents.name + }) + try { + log.info('start') + const schedule = await this.getSchedule(scheduleName) + + const req = formatReq({ ...schedule, ...params, name: scheduleName }) + const command = new UpdateScheduleCommand(req) + + const res = await this.#client.send(command) + + const data = formatRes(res) + + log.debug({ data }, 'data') + log.info('end') + return data + } catch (err) { + log.error({ err }, 'fail') + throw err + } + } +} + +const formatReq = keysToPascalCase +const formatRes = keysToCamelCase