Initial implementation of TechDocs cache in backend plugin
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
committed by
Eric Peterson
parent
3e443e8e31
commit
0a44eb7d52
Vendored
+17
@@ -226,6 +226,23 @@ export interface Config {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @example http://localhost:7007/api/techdocs
|
||||
* Techdocs cache information
|
||||
*/
|
||||
cache?: {
|
||||
/**
|
||||
* The cache time-to-live for TechDocs sites (in milliseconds). Set this
|
||||
* to a non-zero value to cache TechDocs sites and assets as they are
|
||||
* read from storage.
|
||||
*
|
||||
* Note: you must also configure `backend.cache` appropriately as well,
|
||||
* and to pass a PluginCacheManager instance to TechDocs Backend's
|
||||
* createRouter method in your backend.
|
||||
*/
|
||||
ttl: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* @example http://localhost:7007/api/techdocs
|
||||
* @visibility frontend
|
||||
|
||||
@@ -36,6 +36,7 @@ import path from 'path';
|
||||
import { Writable } from 'stream';
|
||||
import { Logger } from 'winston';
|
||||
import { BuildMetadataStorage } from './BuildMetadataStorage';
|
||||
import { TechDocsCache } from '../cache';
|
||||
|
||||
type DocsBuilderArguments = {
|
||||
preparers: PreparerBuilder;
|
||||
@@ -46,6 +47,7 @@ type DocsBuilderArguments = {
|
||||
config: Config;
|
||||
scmIntegrations: ScmIntegrationRegistry;
|
||||
logStream?: Writable;
|
||||
cache?: TechDocsCache;
|
||||
};
|
||||
|
||||
export class DocsBuilder {
|
||||
@@ -57,6 +59,7 @@ export class DocsBuilder {
|
||||
private config: Config;
|
||||
private scmIntegrations: ScmIntegrationRegistry;
|
||||
private logStream: Writable | undefined;
|
||||
private cache?: TechDocsCache;
|
||||
|
||||
constructor({
|
||||
preparers,
|
||||
@@ -67,6 +70,7 @@ export class DocsBuilder {
|
||||
config,
|
||||
scmIntegrations,
|
||||
logStream,
|
||||
cache,
|
||||
}: DocsBuilderArguments) {
|
||||
this.preparer = preparers.get(entity);
|
||||
this.generator = generators.get(entity);
|
||||
@@ -76,6 +80,7 @@ export class DocsBuilder {
|
||||
this.config = config;
|
||||
this.scmIntegrations = scmIntegrations;
|
||||
this.logStream = logStream;
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,11 +215,16 @@ export class DocsBuilder {
|
||||
)}`,
|
||||
);
|
||||
|
||||
await this.publisher.publish({
|
||||
const published = await this.publisher.publish({
|
||||
entity: this.entity,
|
||||
directory: outputDir,
|
||||
});
|
||||
|
||||
// Invalidate the cache for any published objects.
|
||||
if (this.cache && published?.objects?.length) {
|
||||
await this.cache.invalidateMultiple(published.objects);
|
||||
}
|
||||
|
||||
try {
|
||||
// Not a blocker hence no need to await this.
|
||||
fs.remove(outputDir);
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import {
|
||||
PluginEndpointDiscovery,
|
||||
PluginCacheManager,
|
||||
} from '@backstage/backend-common';
|
||||
import { CatalogClient } from '@backstage/catalog-client';
|
||||
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -31,6 +34,7 @@ import { Knex } from 'knex';
|
||||
import { Logger } from 'winston';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer';
|
||||
import { createCacheMiddleware, TechDocsCache } from '../cache';
|
||||
|
||||
/**
|
||||
* All of the required dependencies for running TechDocs in the "out-of-the-box"
|
||||
@@ -44,6 +48,7 @@ type OutOfTheBoxDeploymentOptions = {
|
||||
discovery: PluginEndpointDiscovery;
|
||||
database?: Knex; // TODO: Make database required when we're implementing database stuff.
|
||||
config: Config;
|
||||
cache?: PluginCacheManager;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -88,6 +93,14 @@ export async function createRouter(
|
||||
scmIntegrations,
|
||||
});
|
||||
|
||||
// Set up a cache client if configured.
|
||||
let cache: TechDocsCache | undefined;
|
||||
const defaultTtl = config.getOptionalNumber('techdocs.cache.ttl');
|
||||
if (isOutOfTheBoxOption(options) && options.cache && defaultTtl) {
|
||||
const cacheClient = options.cache.getClient({ defaultTtl });
|
||||
cache = new TechDocsCache({ cache: cacheClient, logger });
|
||||
}
|
||||
|
||||
router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => {
|
||||
const { kind, namespace, name } = req.params;
|
||||
const entityName = { kind, namespace, name };
|
||||
@@ -199,6 +212,11 @@ export async function createRouter(
|
||||
);
|
||||
});
|
||||
|
||||
// If a cache manager was provided, attach the cache middleware.
|
||||
if (cache) {
|
||||
router.use(createCacheMiddleware({ logger, cache }));
|
||||
}
|
||||
|
||||
// Route middleware which serves files from the storage set in the publisher.
|
||||
router.use('/static/docs', publisher.docsRouter());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user