mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-01 02:41:39 -05:00
Removed public-resource-repository
refs https://github.com/TryGhost/Toolbox/issues/522 - Using a generic resource repository for caching purposes didn't prove to be effective as code was moved to api-level caching. There's no need to introduce extra abstraction level for simple calls like findPage when there's no extra logic to it.
This commit is contained in:
parent
b8bdd3e742
commit
6b72b2f51f
9 changed files with 0 additions and 262 deletions
|
@ -126,7 +126,6 @@
|
|||
"@tryghost/package-json": "0.0.0",
|
||||
"@tryghost/pretty-cli": "1.2.33",
|
||||
"@tryghost/promise": "0.2.1",
|
||||
"@tryghost/public-resource-repository": "0.0.0",
|
||||
"@tryghost/request": "0.1.34",
|
||||
"@tryghost/security": "0.0.0",
|
||||
"@tryghost/session-service": "0.0.0",
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: ['ghost'],
|
||||
extends: [
|
||||
'plugin:ghost/node'
|
||||
]
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
# Tags Public
|
||||
|
||||
services and repositories serving public resource endpoints e.g. Tags/Posts/Authors Content API endpoints
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
## Develop
|
||||
|
||||
This is a monorepo package.
|
||||
|
||||
Follow the instructions for the top-level repo.
|
||||
1. `git clone` this repo & `cd` into it as usual
|
||||
2. Run `yarn` to install top-level dependencies.
|
||||
|
||||
|
||||
|
||||
## Test
|
||||
|
||||
- `yarn lint` run just eslint
|
||||
- `yarn test` run lint and tests
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./lib/resources-public');
|
|
@ -1,65 +0,0 @@
|
|||
const _ = require('lodash');
|
||||
|
||||
module.exports = class PublicResourcesRepository {
|
||||
/** @type {object} */
|
||||
#Model;
|
||||
|
||||
/** @type {object} */
|
||||
#cache;
|
||||
|
||||
/**
|
||||
* @param {object} deps
|
||||
* @param {object} deps.Model Bookshelf Model instance of TagPublic/Post/Author etc.
|
||||
* @param {object} [deps.cache] cache instance
|
||||
*/
|
||||
constructor(deps) {
|
||||
this.#Model = deps.Model;
|
||||
this.#cache = deps.cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the database for model records
|
||||
* @param {Object} options model options
|
||||
* @returns
|
||||
*/
|
||||
async #getAllDB(options) {
|
||||
return this.#Model.findPage(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all records from the storage (cache or database)
|
||||
* @param {Object} options
|
||||
* @returns
|
||||
*/
|
||||
async getAll(options) {
|
||||
let cacheKey;
|
||||
|
||||
if (this.#cache) {
|
||||
// make the cache key smaller and don't include context
|
||||
const permittedOptions = this.#Model.permittedOptions('findPage')
|
||||
.filter(option => (option !== 'context'));
|
||||
const optionsForCacheKey = _.pick(options, permittedOptions);
|
||||
|
||||
// NOTE: can be more aggressive here with filtering options,
|
||||
// for example, do we care make a distinction for logged
|
||||
// in member on the repository level?
|
||||
cacheKey = `get-all-${JSON.stringify(optionsForCacheKey)}`;
|
||||
const cachedResult = await this.#cache.get(cacheKey);
|
||||
|
||||
// NOTE: if the cache result is empty still going to the DB
|
||||
// this check can be removed if we want to be more aggressive
|
||||
// with caching and avoid and extra DB call
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
}
|
||||
|
||||
const dbResult = await this.#getAllDB(options);
|
||||
|
||||
if (this.#cache) {
|
||||
await this.#cache.set(cacheKey, dbResult);
|
||||
}
|
||||
|
||||
return dbResult;
|
||||
}
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
module.exports.PublicResourcesRepository = require('./PublicResourcesRepository');
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"name": "@tryghost/public-resource-repository",
|
||||
"version": "0.0.0",
|
||||
"repository": "https://github.com/TryGhost/Ghost/tree/main/packages/tags-public",
|
||||
"author": "Ghost Foundation",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "echo \"Implement me!\"",
|
||||
"test:unit": "NODE_ENV=testing c8 --all --check-coverage --100 --reporter text --reporter cobertura mocha './test/**/*.test.js'",
|
||||
"test": "yarn test:unit",
|
||||
"lint:code": "eslint *.js lib/ --ext .js --cache",
|
||||
"lint": "yarn lint:code && yarn lint:test",
|
||||
"lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"lib"
|
||||
],
|
||||
"devDependencies": {
|
||||
"c8": "7.13.0",
|
||||
"mocha": "10.2.0",
|
||||
"sinon": "15.0.1"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: ['ghost'],
|
||||
extends: [
|
||||
'plugin:ghost/test'
|
||||
]
|
||||
};
|
|
@ -1,133 +0,0 @@
|
|||
const assert = require('assert');
|
||||
const sinon = require('sinon');
|
||||
|
||||
const {PublicResourcesRepository} = require('../index');
|
||||
// @NOTE: This is a dirty import from the Ghost "core"!
|
||||
// extract it to it's own package and import here as require('@tryghost/adapter-base-cache-memory');
|
||||
const MemoryCache = require('../../core/core/server/adapters/cache/Memory');
|
||||
|
||||
describe('PublicResourcesRepository', function () {
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
describe('getAll', function () {
|
||||
it('calls findPage on the model multiple times when cache NOT present', async function () {
|
||||
const tagModelStub = {
|
||||
findPage: sinon.stub().resolves(),
|
||||
permittedOptions: sinon.stub()
|
||||
};
|
||||
const repo = new PublicResourcesRepository({
|
||||
Model: tagModelStub
|
||||
});
|
||||
|
||||
// first call
|
||||
await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
// second call
|
||||
await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
|
||||
assert.equal(tagModelStub.findPage.callCount, 2, 'should be called same amount of times as getAll');
|
||||
assert.ok(tagModelStub.findPage.calledWith({limit: 'all'}));
|
||||
});
|
||||
|
||||
it('calls findPage once and uses the cached value on subsequent calls', async function () {
|
||||
const tagModelStub = {
|
||||
findPage: sinon.stub().resolves({
|
||||
data: [{
|
||||
get(key) {
|
||||
return key;
|
||||
}
|
||||
}],
|
||||
meta: {}
|
||||
}),
|
||||
permittedOptions: sinon.stub().returns(['limit'])
|
||||
};
|
||||
const repo = new PublicResourcesRepository({
|
||||
Model: tagModelStub,
|
||||
cache: new MemoryCache()
|
||||
});
|
||||
|
||||
// first call
|
||||
const dbTags = await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
// second call
|
||||
const cacheTags = await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
|
||||
assert.equal(tagModelStub.findPage.callCount, 1, 'should be called once when cache is present');
|
||||
assert.ok(tagModelStub.findPage.calledWith({limit: 'all'}));
|
||||
|
||||
assert.equal(dbTags, cacheTags, 'should return the same value from the cache');
|
||||
});
|
||||
|
||||
it('calls findPage multiple times if the record is not present in the cache', async function () {
|
||||
const tagModelStub = {
|
||||
findPage: sinon.stub().resolves({
|
||||
data: [{
|
||||
get(key) {
|
||||
return key;
|
||||
}
|
||||
}],
|
||||
meta: {}
|
||||
}),
|
||||
permittedOptions: sinon.stub().returns(['limit'])
|
||||
};
|
||||
const cache = new MemoryCache();
|
||||
const repo = new PublicResourcesRepository({
|
||||
Model: tagModelStub,
|
||||
cache: cache
|
||||
});
|
||||
|
||||
// first call
|
||||
await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
|
||||
// clear the cache
|
||||
cache.reset();
|
||||
|
||||
// second call
|
||||
await repo.getAll({
|
||||
limit: 'all'
|
||||
});
|
||||
|
||||
assert.equal(tagModelStub.findPage.callCount, 2, 'should be called every time the item is not in the cache');
|
||||
assert.ok(tagModelStub.findPage.calledWith({limit: 'all'}));
|
||||
});
|
||||
|
||||
it('works with a cache that has an asynchronous interface', async function () {
|
||||
const tagModelStub = {
|
||||
findPage: sinon.stub().resolves({
|
||||
data: [{
|
||||
get(key) {
|
||||
return key;
|
||||
}
|
||||
}],
|
||||
meta: {}
|
||||
}),
|
||||
permittedOptions: sinon.stub().returns(['limit'])
|
||||
};
|
||||
|
||||
const asyncMemoryCache = {
|
||||
get: sinon.stub().resolves('test'),
|
||||
set: sinon.stub().resolves()
|
||||
};
|
||||
|
||||
const repo = new PublicResourcesRepository({
|
||||
Model: tagModelStub,
|
||||
cache: asyncMemoryCache
|
||||
});
|
||||
|
||||
const result = await repo.getAll();
|
||||
|
||||
assert.ok(asyncMemoryCache.get.calledOnce);
|
||||
assert.equal('test', result, 'should return the value from the cache');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue