Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement/bb 541 avoid initializing mongodb client #2553

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 62 additions & 46 deletions lib/api/BackbeatAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -1260,40 +1260,10 @@
this._healthcheck = new Healthcheck(this._repConfig, this._zkClient,
this._crrProducer, this._crrStatusProducer,
this._metricProducer);
this._locationStatusManager = new LocationStatusManager(
this._mongoClient,
this._zkClient,
this._redisPublisher,
{
crr: {
namespace: zookeeperReplicationNamespace,
statePath: zkReplicationStatePath,
topic: this._crrTopic,
isMongo: false,
},
ingestion: {
namespace: zookeeperIngestionNamespace,
statePath: zkIngestionStatePath,
topic: this._ingestionTopic,
isMongo: false,
},
lifecycle: {
isMongo: true,
}
},
this._logger,
);
return this._locationStatusManager._setupLocationStatusStore(err => {
if (err) {
this._logger.error('error setting up location status manager', {
method: 'BackbeatAPI.setupInternals',
error: err.message,
});
return cb(err);
}
this._logger.info('BackbeatAPI setup ready');
return cb();
});
if (this._queuePopulator.mongo) {
return this._setupLocationStatusManager(cb);
}
return cb();
});
}

Expand Down Expand Up @@ -1336,26 +1306,72 @@
*/
_setupMongoClient(cb) {
const mongoConfig = this._config.queuePopulator.mongo;
const mongoUrl = constructConnectionString(mongoConfig);
MongoClient.connect(mongoUrl, {
if (!mongoConfig) {
this._logger.debug('MongoDB configuration not found, skipping MongoDB client setup', {
method: 'BackbeatAPI._setupMongoClient',
});
return cb();
} else {
// To be removed once the mongodb drivers are bumped
// BB-585
const mongoUrl = constructConnectionString(mongoConfig);
return MongoClient.connect(mongoUrl, {
replicaSet: mongoConfig.replicaSet,
useNewUrlParser: true,
useUnifiedTopology: true,
benzekrimaha marked this conversation as resolved.
Show resolved Hide resolved
}, (err, client) => {
if (err) {
this._logger.error('Could not connect to MongoDB', {
}, (err, client) => {
if (err) {
this._logger.error('Could not connect to MongoDB', {
method: 'BackbeatAPI._setupMongoClient',
error: err.message,
});
return cb(err);
}
// connect to metadata DB
this._mongoClient = client.db(mongoConfig.database, {
ignoreUndefined: true,
});
this._logger.info('Connected to MongoDB', {
method: 'BackbeatAPI._setupMongoClient',
});
return cb();
});
}
}

_setupLocationStatusManager(cb) {
this._locationStatusManager = new LocationStatusManager(
this._mongoClient,
this._zkClient,
this._redisPublisher,
{
crr: {
namespace: zookeeperReplicationNamespace,
statePath: zkReplicationStatePath,
topic: this._crrTopic,
isMongo: false,
},
ingestion: {
namespace: zookeeperIngestionNamespace,
statePath: zkIngestionStatePath,
topic: this._ingestionTopic,
isMongo: false,
},
lifecycle: {
isMongo: true,
}
},
this._logger,
);

return this._locationStatusManager._setupLocationStatusStore(err => {
if (err) {
this._logger.error('error setting up location status manager', {

Check warning on line 1369 in lib/api/BackbeatAPI.js

View check run for this annotation

Codecov / codecov/patch/Backbeat

lib/api/BackbeatAPI.js#L1369

Added line #L1369 was not covered by tests
method: 'BackbeatAPI._setupLocationStatusManager',
error: err.message,
});
return cb(err);
}
// connect to metadata DB
this._mongoClient = client.db(mongoConfig.database, {
ignoreUndefined: true,
});
this._logger.info('Connected to MongoDB', {
method: 'BackbeatAPI._setupMongoClient',
});
return cb();
});
}
Expand Down
121 changes: 121 additions & 0 deletions tests/unit/api/BackbeatAPI.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const assert = require('assert');
const sinon = require('sinon');
const MongoClient = require('mongodb').MongoClient;

const BackbeatAPI = require('../../../lib/api/BackbeatAPI');
const BackbeatRequest = require('../../../lib/api/BackbeatRequest');
Expand Down Expand Up @@ -210,4 +212,123 @@ describe('BackbeatAPI', () => {
assert.deepStrictEqual(sites, params.expected);
});
});

describe('_setupMongoClient', () => {
let mongoClientStub;
let infoSpy;
let errorSpy;
let debugSpy;

beforeEach(() => {
mongoClientStub = sinon.stub(MongoClient, 'connect');
infoSpy = sinon.spy(fakeLogger, 'info');
errorSpy = sinon.spy(fakeLogger, 'error');
debugSpy = sinon.spy(fakeLogger, 'debug');
});

afterEach(() => {
mongoClientStub.restore();
infoSpy.restore();
errorSpy.restore();
debugSpy.restore();
});

it('should connect to MongoDB when configuration is present', done => {
const mockDb = { db: sinon.stub().returns({}) };
mongoClientStub.yields(null, mockDb);

bbapi._setupMongoClient(err => {
assert.ifError(err);
assert(mongoClientStub.calledOnce);
assert(infoSpy.calledWith('Connected to MongoDB', {
method: 'BackbeatAPI._setupMongoClient',
}));
done();
});
});

it('should log an error when MongoDB connection fails', done => {
const mockError = new Error('Connection failed');
mongoClientStub.yields(mockError);

bbapi._setupMongoClient(err => {
assert.strictEqual(err, mockError);
assert(mongoClientStub.calledOnce);
assert(errorSpy.calledWith('Could not connect to MongoDB', {
method: 'BackbeatAPI._setupMongoClient',
error: mockError.message,
}));
done();
});
});

it('should skip MongoDB client setup when configuration is not present', done => {
delete bbapi._config.queuePopulator.mongo;

bbapi._setupMongoClient(err => {
assert.ifError(err);
assert(mongoClientStub.notCalled);
assert(debugSpy.calledWith('MongoDB configuration not found, skipping MongoDB client setup', {
method: 'BackbeatAPI._setupMongoClient',
}));
done();
});
});
});

describe('setupInternals', () => {
let setZookeeperStub;
let setupMongoClientStub;
let setProducerStub;
let setupLocationStatusManagerStub;
let errorSpy;
let debugSpy;

beforeEach(() => {
setZookeeperStub = sinon.stub(bbapi, '_setZookeeper').yields(null);
setupMongoClientStub = sinon.stub(bbapi, '_setupMongoClient').yields(null);
setProducerStub = sinon.stub(bbapi, '_setProducer').yields(null, {});
setupLocationStatusManagerStub = sinon.stub(bbapi, '_setupLocationStatusManager').yields(null);
errorSpy = sinon.spy(fakeLogger, 'error');
debugSpy = sinon.spy(fakeLogger, 'debug');
});

afterEach(() => {
setZookeeperStub.restore();
setupMongoClientStub.restore();
setProducerStub.restore();
setupLocationStatusManagerStub.restore();
errorSpy.restore();
debugSpy.restore();
});

it('should setup internals when MongoDB configuration exists', done => {
bbapi._config.queuePopulator.mongo = {
host: 'localhost',
port: 27017,
db: 'backbeat',
};
bbapi.setupInternals(err => {
assert.ifError(err);
assert(setZookeeperStub.calledOnce);
assert(setupMongoClientStub.calledOnce);
assert(setProducerStub.calledThrice);
assert(setupLocationStatusManagerStub.calledOnce);
done();
});
});

it('should setup internals when MongoDB configuration does not exist', done => {
delete bbapi._config.queuePopulator.mongo;

bbapi.setupInternals(err => {
assert.ifError(err);
assert(setZookeeperStub.calledOnce);
assert(setupMongoClientStub.calledOnce);
assert(setProducerStub.calledThrice);
assert(setupLocationStatusManagerStub.notCalled);
done();
});
});
});
});
Loading