-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(document datasource): add document datasource
- Loading branch information
1 parent
ca204df
commit 274a1d8
Showing
3 changed files
with
137 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
const { DataSource } = require('apollo-datasource'); | ||
const DataLoader = require('dataloader'); | ||
const { aql } = require('arangojs'); | ||
|
||
/** | ||
* An ArangoDb implementation of the Apollo DataSource. | ||
* | ||
* This DataSource is solely for resolving Arando Documents by their Id. | ||
* Requests are batched and cached per request. | ||
* | ||
* @class ArangoDocumentDataSource | ||
* @extends {DataSource} | ||
*/ | ||
class ArangoDocumentDataSource extends DataSource { | ||
/** | ||
* Creates an instance of ArangoDocumentDataSource. | ||
* @param {Database} db | ||
* @memberof ArangoDocumentDataSource | ||
*/ | ||
constructor(db) { | ||
super(); | ||
this.db = db; | ||
} | ||
|
||
/** | ||
* Initializes the DataSource. Called at the beginning of each request. | ||
* | ||
* @memberof ArangoDocumentDataSource | ||
*/ | ||
initialize() { | ||
this.dataloader = new DataLoader(keys => this.loadKeys(keys)); | ||
} | ||
|
||
/** | ||
* Gets a Document by its _id | ||
* | ||
* @param {string} id The _id to query for | ||
* @returns {any} The corresponding Document | ||
* @memberof ArangoDocumentDataSource | ||
*/ | ||
async get(id) { | ||
return this.dataloader.load(id); | ||
} | ||
|
||
/** | ||
* Gets several Documents at once by their _id | ||
* | ||
* @param {string[]} ids The _ids to query for | ||
* @returns {any[]} The corresponding Documents. In the order their Ids were specified in the ids array | ||
* @memberof ArangoDocumentDataSource | ||
*/ | ||
async getMany(ids) { | ||
return this.dataloader.loadMany(ids); | ||
} | ||
|
||
/** | ||
* Queries the database for the given keys. | ||
* | ||
* @param {string[]} keys The keys to qeury for | ||
* @private | ||
* @returns {*[]} The corresponding Documents. In the order their Ids were specified in the ids array | ||
* @memberof ArangoDocumentDataSource | ||
*/ | ||
async loadKeys(keys) { | ||
const cursor = await this.db.query(aql`RETURN DOCUMENT(${keys})`); | ||
const nodes = await cursor.all(); | ||
|
||
return keys.map(key => { | ||
const node = nodes.find(node => node._id === key); | ||
|
||
if (node) { | ||
node.id = node._id; | ||
} | ||
|
||
return node; | ||
}); | ||
} | ||
} | ||
|
||
module.exports = { | ||
ArangoDocumentDataSource: ArangoDocumentDataSource | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const { ArangoDocumentDataSource } = require('.'); | ||
|
||
describe('ArangDocumentDataSource', () => { | ||
test('it batches key loads', async () => { | ||
const results = [{ _id: '123' }, { _id: '456' }]; | ||
const db = createDb(results); | ||
const datasource = new ArangoDocumentDataSource(db); | ||
datasource.initialize(); | ||
|
||
const docs = await Promise.all([ | ||
datasource.get('123'), | ||
datasource.get('456') | ||
]); | ||
|
||
expect(docs).toEqual(results); | ||
expect(db.query).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test('it caches key loads', async () => { | ||
const results = [{ _id: '123' }]; | ||
const db = createDb(results); | ||
const datasource = new ArangoDocumentDataSource(db); | ||
datasource.initialize(); | ||
|
||
for (let i = 0; i < 3; i++) { | ||
const doc = await datasource.get('123'); | ||
expect(db.query).toHaveBeenCalledTimes(1); | ||
expect(doc).toEqual(results[0]); | ||
} | ||
}); | ||
|
||
test('it returns docs for several keys', async () => { | ||
const results = [{ _id: '123' }, { _id: '456' }]; | ||
const db = createDb(results); | ||
const datasource = new ArangoDocumentDataSource(db); | ||
datasource.initialize(); | ||
|
||
const docs = await datasource.getMany(['456', '123']); | ||
|
||
expect(docs).toEqual(results.reverse()); | ||
expect(db.query).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
|
||
function createDb(queryResults) { | ||
return { | ||
query: jest.fn().mockResolvedValue({ | ||
all: () => queryResults | ||
}) | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module.exports = { | ||
...require('./arango-datasource'), | ||
...require('./arango-document-datasource') | ||
}; |