Skip to content

Commit e68e53c

Browse files
committed
Adjust logging
Add context information to errors thrown during definition recomputation. Add more tests
1 parent 0d72a12 commit e68e53c

File tree

4 files changed

+104
-15
lines changed

4 files changed

+104
-15
lines changed

providers/upgrade/defUpgradeQueue.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ class DefinitionQueueUpgrader extends DefinitionVersionChecker {
1919
try {
2020
const message = this._constructMessage(definition)
2121
await this._upgrade.queue(message)
22-
this.logger.debug('Queued for definition upgrade ', {
22+
this.logger.info('Queued for definition upgrade ', {
2323
coordinates: DefinitionVersionChecker.getCoordinates(definition)
2424
})
2525
} catch (error) {
26-
//continue if queuing fails and requeue at the next request.
27-
this.logger.error(`Error queuing for definition upgrade ${error.message}`, {
26+
//continue if queueing fails and requeue at the next request.
27+
this.logger.error(`Error queueing for definition upgrade ${error.message}`, {
2828
error,
2929
coordinates: DefinitionVersionChecker.getCoordinates(definition)
3030
})

providers/upgrade/process.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,20 @@ class DefinitionUpgrader {
6767
}
6868

6969
async _upgradeIfNecessary(coordinates) {
70-
const existing = await this._definitionService.getStored(coordinates)
71-
let result = await this._defVersionChecker.validate(existing)
72-
if (!result) {
73-
await this._definitionService.computeStoreAndCurate(coordinates)
74-
this.logger.info(`Handled definition update for ${coordinates.toString()}`)
75-
} else {
76-
this.logger.debug(`Skipped definition update for ${coordinates.toString()}`)
70+
try {
71+
const existing = await this._definitionService.getStored(coordinates)
72+
let result = await this._defVersionChecker.validate(existing)
73+
if (!result) {
74+
await this._definitionService.computeStoreAndCurate(coordinates)
75+
this.logger.info('Handled definition upgrade for %s', coordinates)
76+
} else {
77+
this.logger.debug('Skipped definition upgrade for %s', coordinates)
78+
}
79+
} catch (error) {
80+
const context = `Error handling definition upgrade for ${coordinates.toString()}`
81+
const newError = new Error(`${context}: ${error.message}`)
82+
newError.stack = error.stack
83+
throw newError
7784
}
7885
}
7986
}

test/providers/upgrade/defUpgradeQueue.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ const DefinitionQueueUpgrader = require('../../../providers/upgrade/defUpgradeQu
1010
const MemoryQueue = require('../../../providers/upgrade/memoryQueueConfig')
1111

1212
describe('DefinitionQueueUpgrader', () => {
13-
const logger = { debug: sinon.stub(), error: sinon.stub() }
13+
let logger
14+
beforeEach(() => {
15+
logger = { debug: sinon.stub(), error: sinon.stub() }
16+
})
1417

1518
describe('Unit tests', () => {
1619
const definition = { coordinates: 'test', _meta: { schemaVersion: '1.0.0' } }

test/providers/upgrade/processTest.js

+83-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
// (c) Copyright 2024, SAP SE and ClearlyDefined contributors. Licensed under the MIT license.
22
// SPDX-License-Identifier: MIT
33

4+
const chaiAsPromised = require('chai-as-promised')
5+
const chai = require('chai')
6+
chai.use(chaiAsPromised)
47
const { expect } = require('chai')
58
const sinon = require('sinon')
69
const { QueueHandler, DefinitionUpgrader } = require('../../../providers/upgrade/process')
10+
const EntityCoordinates = require('../../../lib/entityCoordinates')
711

812
describe('Definition Upgrade Queue Processing', () => {
913
let logger
@@ -80,7 +84,9 @@ describe('Definition Upgrade Queue Processing', () => {
8084
})
8185

8286
describe('DefinitionUpgrader', () => {
83-
const definition = Object.freeze({ coordinates: 'pypi/pypi/-/test/revision' })
87+
const coordinates = 'pypi/pypi/-/test/revision'
88+
const definition = Object.freeze({ coordinates: EntityCoordinates.fromString(coordinates) })
89+
const message = Object.freeze({ data: { coordinates: definition.coordinates } })
8490
let definitionService, versionChecker, upgrader
8591

8692
beforeEach(() => {
@@ -98,7 +104,7 @@ describe('Definition Upgrade Queue Processing', () => {
98104
definitionService.getStored.resolves(definition)
99105
versionChecker.validate.resolves()
100106

101-
await upgrader.processMessage({ data: { coordinates: 'pypi/pypi/-/test/revision' } })
107+
await upgrader.processMessage(message)
102108
expect(definitionService.getStored.calledOnce).to.be.true
103109
expect(versionChecker.validate.calledOnce).to.be.true
104110
expect(definitionService.computeStoreAndCurate.calledOnce).to.be.true
@@ -108,7 +114,7 @@ describe('Definition Upgrade Queue Processing', () => {
108114
definitionService.getStored.resolves(definition)
109115
versionChecker.validate.resolves(definition)
110116

111-
await upgrader.processMessage({ data: { coordinates: 'pypi/pypi/-/test/revision' } })
117+
await upgrader.processMessage(message)
112118
expect(definitionService.getStored.calledOnce).to.be.true
113119
expect(versionChecker.validate.calledOnce).to.be.true
114120
expect(definitionService.computeStoreAndCurate.notCalled).to.be.true
@@ -118,7 +124,7 @@ describe('Definition Upgrade Queue Processing', () => {
118124
definitionService.getStored.resolves()
119125
versionChecker.validate.resolves()
120126

121-
await upgrader.processMessage({ data: { coordinates: 'pypi/pypi/-/test/revision' } })
127+
await upgrader.processMessage(message)
122128
expect(definitionService.getStored.calledOnce).to.be.true
123129
expect(versionChecker.validate.calledOnce).to.be.true
124130
expect(definitionService.computeStoreAndCurate.calledOnce).to.be.true
@@ -130,5 +136,78 @@ describe('Definition Upgrade Queue Processing', () => {
130136
expect(versionChecker.validate.notCalled).to.be.true
131137
expect(definitionService.computeStoreAndCurate.notCalled).to.be.true
132138
})
139+
140+
it('handles exception by rethrowing with coordinates and the original error message', async () => {
141+
definitionService.getStored.resolves(definition)
142+
versionChecker.validate.resolves()
143+
definitionService.computeStoreAndCurate.rejects(new Error('test'))
144+
145+
await expect(upgrader.processMessage(message)).to.be.rejectedWith(Error, /pypi\/pypi\/-\/test\/revision: test/)
146+
})
147+
})
148+
149+
describe('Integration Test', () => {
150+
const definition = Object.freeze({
151+
coordinates: { type: 'pypi', provider: 'pypi', name: 'test', revision: 'revision' },
152+
_meta: { schemaVersion: '0.0.1' }
153+
})
154+
const message = Object.freeze({ data: { ...definition } })
155+
156+
let queue, handler, definitionService, versionChecker
157+
beforeEach(() => {
158+
let definitionUpgrader
159+
;({ definitionService, versionChecker, definitionUpgrader } = setupDefinitionUpgrader(logger))
160+
queue = {
161+
dequeueMultiple: sinon.stub().resolves([message]),
162+
delete: sinon.stub().resolves()
163+
}
164+
handler = new QueueHandler(queue, logger, definitionUpgrader)
165+
})
166+
167+
it('handles exception and logs the coordinates and the original error message', async () => {
168+
definitionService.getStored.resolves(definition)
169+
versionChecker.validate.resolves()
170+
definitionService.computeStoreAndCurate.rejects(new Error('test'))
171+
172+
await handler.work(true)
173+
expect(queue.dequeueMultiple.calledOnce).to.be.true
174+
expect(queue.delete.called).to.be.false
175+
expect(logger.error.calledOnce).to.be.true
176+
expect(logger.error.args[0][0].message).to.match(/pypi\/pypi\/-\/test\/revision: test/)
177+
})
178+
179+
it('skips compute if a definition is up-to-date', async () => {
180+
definitionService.getStored.resolves(definition)
181+
versionChecker.validate.resolves(definition)
182+
183+
await handler.work(true)
184+
expect(definitionService.getStored.calledOnce).to.be.true
185+
expect(versionChecker.validate.calledOnce).to.be.true
186+
expect(definitionService.computeStoreAndCurate.notCalled).to.be.true
187+
expect(queue.delete.called).to.be.true
188+
})
189+
190+
it('recomputes a definition, if a definition is not up-to-date', async () => {
191+
definitionService.getStored.resolves(definition)
192+
versionChecker.validate.resolves()
193+
await handler.work(true)
194+
expect(definitionService.getStored.calledOnce).to.be.true
195+
expect(versionChecker.validate.calledOnce).to.be.true
196+
expect(definitionService.computeStoreAndCurate.calledOnce).to.be.true
197+
expect(queue.delete.called).to.be.true
198+
})
133199
})
134200
})
201+
202+
function setupDefinitionUpgrader(logger) {
203+
const definitionService = {
204+
getStored: sinon.stub(),
205+
computeStoreAndCurate: sinon.stub().resolves()
206+
}
207+
const versionChecker = {
208+
validate: sinon.stub()
209+
}
210+
const definitionUpgrader = new DefinitionUpgrader(definitionService, logger, versionChecker)
211+
return { definitionService, versionChecker, definitionUpgrader }
212+
}
213+

0 commit comments

Comments
 (0)