Skip to content

Commit c39c085

Browse files
committed
Addressed bugs outlined #321
1 parent 9600153 commit c39c085

5 files changed

Lines changed: 45 additions & 54 deletions

File tree

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
FROM registry.access.redhat.com/ubi9/nodejs-22:latest AS build-env
1+
FROM registry.access.redhat.com/ubi9/nodejs-24:latest AS build-env
22
WORKDIR /opt/app-root/src
33
COPY --chown=default:root job/* .
44
RUN npm install
55

66
# Use a small distroless image for as runtime image
7-
FROM gcr.io/distroless/nodejs22
7+
FROM gcr.io/distroless/nodejs24
88
COPY --from=build-env /opt/app-root/src /app
99
WORKDIR /app
10-
ENTRYPOINT ["job.mjs"]
10+
CMD ["job.mjs"]

cloudant-change-listener/job/ce-api-utils.mjs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
1-
import log4js from "log4js";
21
import { IamAuthenticator } from "ibm-cloud-sdk-core";
32
import CodeEngineV2 from "@ibm-cloud/ibm-code-engine-sdk/dist/code-engine/v2.js";
3+
import winston from "winston";
4+
const { combine, json } = winston.format;
45

5-
//
6-
// use a formatted logger to have timestamps in the log output
7-
log4js.configure({
8-
appenders: {
9-
out: { type: "stdout" },
10-
},
11-
categories: {
12-
default: { appenders: ["out"], level: process.env.LOGLEVEL || "debug" },
13-
},
6+
const logger = winston.createLogger({
7+
level: "debug",
8+
transports: [new winston.transports.Console()],
9+
format: combine(json()),
1410
});
15-
const logger = log4js.getLogger();
1611

1712
let codeEngineApi;
1813
function getCodeEngineApi() {
1914
if (!codeEngineApi) {
2015
// Extracting the region from the CE_DOMAIN (us-south.codeengine.appdomain.cloud)
2116
const region = process.env.CE_DOMAIN.substring(0, process.env.CE_DOMAIN.indexOf("."));
22-
logger.trace(`CE_DOMAIN: '${process.env.CE_DOMAIN}', region: '${region}'`);
17+
logger.debug(`CE_DOMAIN: '${process.env.CE_DOMAIN}', region: '${region}'`);
2318

2419
// Construct the Code Engine client using the IAM authenticator.
2520
// see: https://cloud.ibm.com/apidocs/codeengine/v2?code=node#authentication
@@ -36,17 +31,17 @@ function getCodeEngineApi() {
3631

3732
export async function getJobConfig(projectId, configMapName) {
3833
const fn = "getJobConfig ";
39-
logger.trace(`${fn}> configMapName: '${configMapName}'`);
34+
logger.debug(`${fn}> configMapName: '${configMapName}'`);
4035
const configMap = await getConfigMap(projectId, configMapName);
41-
logger.trace(`${fn}< configmap '${configMapName}' exists `);
36+
logger.debug(`${fn}< configmap '${configMapName}' exists `);
4237
return configMap;
4338
}
4439

4540
export async function updateJobConfig(projectId, configMapName, configDataToUpdate) {
4641
const fn = "updateJobConfig ";
47-
logger.trace(`${fn}> configMapName: '${configMapName}', configDataToUpdate: '${JSON.stringify(configDataToUpdate)}'`);
42+
logger.debug(`${fn}> configMapName: '${configMapName}', configDataToUpdate: '${JSON.stringify(configDataToUpdate)}'`);
4843
const updatedConfigMap = await updateConfigMap(projectId, configMapName, configDataToUpdate);
49-
logger.trace(`${fn}< updated configmap '${JSON.stringify(updatedConfigMap)}'`);
44+
logger.debug(`${fn}< updated configmap '${JSON.stringify(updatedConfigMap)}'`);
5045
}
5146

5247
export async function isJobAlreadyRunning(projectId, jobName) {
@@ -55,7 +50,7 @@ export async function isJobAlreadyRunning(projectId, jobName) {
5550

5651
try {
5752
const jobRunList = await listJobRuns(projectId, jobName);
58-
logger.trace(`${fn}- jobRunList: '${JSON.stringify(jobRunList)}'`);
53+
logger.debug(`${fn}- jobRunList: '${JSON.stringify(jobRunList)}'`);
5954

6055
if (!jobRunList || !Array.isArray(jobRunList)) {
6156
logger.debug(`${fn}< false - unexpected response`);
@@ -115,7 +110,7 @@ async function listJobRuns(projectId, jobName) {
115110
logger.debug(`Successfully listed all runs of job '${jobName}' - duration: ${Date.now() - startTime}ms`);
116111
return allResults;
117112
} catch (err) {
118-
logger.error(`Failed to list runs of job '${jobName}', err =`, err);
113+
logger.error(`Failed to list runs of job '${jobName}'`, err);
119114
throw err;
120115
}
121116
}
@@ -142,7 +137,7 @@ async function updateConfigMap(projectId, name, configData) {
142137
logger.debug(`Successfully updated ConfigMap '${name}' - duration: ${Date.now() - startTime}ms`);
143138
return res.result;
144139
} catch (err) {
145-
logger.error(`Failed to update ConfigMap '${JSON.stringify(params)}', err =`, err);
140+
logger.error(`Failed to update ConfigMap '${JSON.stringify(params)}'`, err);
146141
throw err;
147142
}
148143
}
@@ -166,7 +161,7 @@ async function getConfigMap(projectId, name) {
166161
logger.debug(`Successfully read ConfigMap '${name}' - duration: ${Date.now() - startTime}ms`);
167162
return res.result;
168163
} catch (err) {
169-
logger.error(`Failed to read ConfigMap '${JSON.stringify(params)}', err =`, err);
164+
logger.error(`Failed to read ConfigMap '${JSON.stringify(params)}'`, err);
170165
throw err;
171166
}
172167
}

cloudant-change-listener/job/job.mjs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
* - CLOUDANTNOSQLDB_PORT (optional) DB port number (default: 443)
6363
* - CLOUDANTNOSQLDB_APIKEY The IBM Cloud IAM APIkey if using IAMAuthentication on DB connection
6464
* - DB_NAME The name of the DB to listen on. e.g "MyTestDB"
65-
* - DB_LAST_SEQ (optional) last_seq value to use as start identifier for db changes feed.
65+
* - DB_LAST_SEQ (optional) lastSeq value to use as start identifier for db changes feed.
6666
* - CE_TARGET Full URL of the target Code Engine function or application that should receive events
6767
* - DB_POST_CHANGES_TIMEOUT Max wait-time in milliseconds on each long-polling call to the DB (default: 8000)
6868
* The poll timeout can be used to adapt the listening timeout to the settings defined on the cloudant DB
@@ -73,21 +73,17 @@
7373
*************************************************************************************/
7474
import { CloudantV1 } from "@ibm-cloud/cloudant";
7575
import { BasicAuthenticator, IamAuthenticator } from "ibm-cloud-sdk-core";
76-
import log4js from "log4js";
7776
import { LRUCache } from "lru-cache";
7877
import { isJobAlreadyRunning, updateJobConfig, getJobConfig } from "./ce-api-utils.mjs";
78+
import winston from "winston";
79+
const { combine, json } = winston.format;
7980

80-
//
81-
// use a formatted logger to have timestamps in the log output
82-
log4js.configure({
83-
appenders: {
84-
out: { type: "stdout" },
85-
},
86-
categories: {
87-
default: { appenders: ["out"], level: process.env.LOGLEVEL || "info" },
88-
},
81+
const logger = winston.createLogger({
82+
level: "debug",
83+
transports: [new winston.transports.Console()],
84+
format: combine(json()),
8985
});
90-
const logger = log4js.getLogger();
86+
9187

9288
logger.info('Starting Cloudant DB change listener ...');
9389

@@ -358,7 +354,7 @@ function dbChangeHandler(change) {
358354
logger.info(`Successfully called CE URL of app or function with response: '${httpRes.status}' - duration: ${Date.now() - startTime}ms`);
359355
})
360356
.catch((err) => {
361-
logger.error(`Failed to call CE URL of app or function'${targetCEUrl}', err =`, err);
357+
logger.error(`Failed to call CE URL of app or function '${targetCEUrl}'`, err);
362358
});
363359
}
364360

@@ -433,7 +429,7 @@ async function doListen() {
433429
//* change from which the listening starts. This since option is controlled in
434430
//* this loop by following rules:
435431
//* - use DB_LAST_SEQ value on first cycle of loop
436-
//* - if waitForDbChanges() call provides a valid last_seq value in response, then
432+
//* - if waitForDbChanges() call provides a valid lastSeq value in response, then
437433
//* use this value for the next run of the loop
438434
//* - if waitForDbChanges() call fails with timeout or retryalbe error,
439435
//* then re-run with same seq value as in the previous loop cycle
@@ -454,7 +450,7 @@ async function doListen() {
454450

455451
//
456452
// Response exist when waitForDbChanges returns OK
457-
// If response.result.results == 0 = { "results": [] , "last_seq" : value } means timeout occur
453+
// If response.result.results == 0 = { "results": [] , "lastSeq" : value } means timeout occur
458454
// If response = <value> Doc change received ( feed.on(data,..))
459455
if (Object.keys(response).length === 0) {
460456
logger.info("Cloudant-SDK provided an unexpected empty response object on postChanges() call. Continue listening");
@@ -464,15 +460,15 @@ async function doListen() {
464460

465461
if (!response || !response.result) {
466462
sinceToken = "now";
467-
logger.info(`Got Ok postChanges result, but not a valid last_seq value. Start fresh by pulling only new changes.`);
463+
logger.info(`Got Ok postChanges result, but not a valid lastSeq value. Start fresh by pulling only new changes.`);
468464
continue; // run waitForDbChanges with new since token
469465
}
470466

471-
if (Array.isArray(response.result.results) && response.result.results.length === 0 && response.result.last_seq) {
467+
if (Array.isArray(response.result.results) && response.result.results.length === 0 && response.result.lastSeq) {
472468
//
473469
// Wait timed out and delivered the lastSeq value as start point for the next loop
474-
sinceToken = response.result.last_seq;
475-
lastHandledSeq = response.result.last_seq;
470+
sinceToken = response.result.lastSeq;
471+
lastHandledSeq = response.result.lastSeq;
476472
logger.info(`No changes detected in the given wait period. Assigned new since token from result.`);
477473
continue; // run waitForDbChanges with updated since token
478474
}
@@ -486,9 +482,9 @@ async function doListen() {
486482
});
487483

488484
//
489-
// Get the last_seq value to use in the next postChanges() query
490-
sinceToken = response.result.last_seq;
491-
lastHandledSeq = response.result.last_seq;
485+
// Get the lastSeq value to use in the next postChanges() query
486+
sinceToken = response.result.lastSeq;
487+
lastHandledSeq = response.result.lastSeq;
492488
continue; // run waitForDbChanges with updated since token
493489
}
494490

@@ -497,7 +493,7 @@ async function doListen() {
497493
// valid lastSeq number then continue the wrapper loop with
498494
// since = now
499495
sinceToken = "now";
500-
logger.info(`Got Ok postChanges result, but not a valid last_seq value. Start fresh by pulling only new changes.`);
496+
logger.info(`Got Ok postChanges result, but not a valid lastSeq value. Start fresh by pulling only new changes.`);
501497
continue;
502498
} catch (err) {
503499
// Handle how to proceed loop in case of WRAPPER_TIMEOUT
@@ -512,7 +508,7 @@ async function doListen() {
512508
continue;
513509
}
514510

515-
logger.error("Error in waitForDbChanges loop, err = ", err);
511+
logger.error("Error in waitForDbChanges loop", err);
516512

517513
// In case of unexpected error occur, then continue
518514
// with wrapper loop and since = 'now'

cloudant-change-listener/job/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Change event listener for cloudant DB",
55
"main": "job.mjs",
66
"engines": {
7-
"node": "^22",
7+
"node": "^24",
88
"npm": "^11"
99
},
1010
"scripts": {
@@ -14,10 +14,10 @@
1414
"author": "",
1515
"license": "ISC",
1616
"dependencies": {
17-
"@ibm-cloud/cloudant": "^0.12.7",
18-
"@ibm-cloud/ibm-code-engine-sdk": "^4.0.0",
19-
"ibm-cloud-sdk-core": "^5.4.2",
20-
"lru-cache": "^10.0.3",
21-
"log4js": "^6.9.1"
17+
"@ibm-cloud/cloudant": "^0.12.16",
18+
"@ibm-cloud/ibm-code-engine-sdk": "^5.0.0",
19+
"ibm-cloud-sdk-core": "^5.4.9",
20+
"lru-cache": "^11.2.7",
21+
"winston": "^3.19.0"
2222
}
2323
}

fotobox/frontend-app/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ RUN npm ci --omit dev
2020

2121
EXPOSE 3000
2222

23-
ENTRYPOINT [ "node", "build" ]
23+
CMD [ "node", "build" ]
2424

2525

0 commit comments

Comments
 (0)