diff --git a/.changeset/cache-me-if-you-can.md b/.changeset/cache-me-if-you-can.md new file mode 100644 index 0000000000..4322d1158f --- /dev/null +++ b/.changeset/cache-me-if-you-can.md @@ -0,0 +1,82 @@ +--- +'@backstage/create-app': patch +--- + +Cache management has been added to the Backstage backend. + +To apply this change to an existing app, make the following changes: + +```diff +// packages/backend/src/types.ts + +import { Logger } from 'winston'; +import { Config } from '@backstage/config'; +import { ++ PluginCacheManager, + PluginDatabaseManager, + PluginEndpointDiscovery, + UrlReader, +} from '@backstage/backend-common'; + +export type PluginEnvironment = { + logger: Logger; + database: PluginDatabaseManager; ++ cache: PluginCacheManager; + config: Config; + reader: UrlReader + discovery: PluginEndpointDiscovery; +}; +``` + +```diff +// packages/backend/src/index.ts + +import Router from 'express-promise-router'; +import { + createServiceBuilder, + loadBackendConfig, + getRootLogger, + useHotMemoize, + notFoundHandler, ++ CacheManager, + SingleConnectionDatabaseManager, + SingleHostDiscovery, + UrlReaders, +} from '@backstage/backend-common'; +import { Config } from '@backstage/config'; + +function makeCreateEnv(config: Config) { + const root = getRootLogger(); + const reader = UrlReaders.default({ logger: root, config }); + const discovery = SingleHostDiscovery.fromConfig(config); + + root.info(`Created UrlReader ${reader}`); + + const databaseManager = SingleConnectionDatabaseManager.fromConfig(config); ++ const cacheManager = CacheManager.fromConfig(config); + + return (plugin: string): PluginEnvironment => { + const logger = root.child({ type: 'plugin', plugin }); + const database = databaseManager.forPlugin(plugin); +- return { logger, database, config, reader, discovery }; ++ const cache = cacheManager.forPlugin(plugin); ++ return { logger, database, cache, config, reader, discovery }; + }; +} +``` + +To configure a cache store, add a `backend.cache` key to your app-config.yaml. + +```diff +// app-config.yaml + +backend: + baseUrl: http://localhost:7000 + listen: + port: 7000 + database: + client: sqlite3 + connection: ':memory:' ++ cache: ++ store: memory +``` diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index c367fa0a4c..b8f028a2ae 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -113,6 +113,7 @@ json jsonnet jsx Kaewkasi +Keyv Knex kubectl kubernetes diff --git a/app-config.yaml b/app-config.yaml index b1c915f85a..9874ce37ac 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -29,6 +29,8 @@ backend: database: client: sqlite3 connection: ':memory:' + cache: + store: memory cors: origin: http://localhost:3000 methods: [GET, POST, PUT, DELETE] diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index 316f066614..af46a8c830 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -182,6 +182,21 @@ work but [aren't tested as fully](https://github.com/backstage/backstage/issues/2460) yet. +## Cache + +The Backstage backend and its builtin plugins are also able to leverage cache +stores as a means of improving performance or reliability. Similar to how +databases are supported, plugins receive logically separated cache connections, +which are powered by [Keyv](https://github.com/lukechilds/keyv) under the hood. + +At this time of writing, Backstage can be configured to use one of two cache +stores: memory, which is mainly used for local testing, and memcache, which is a +cache store better suited for production deployment. The right cache store for +your Backstage instance will depend on your own run-time constraints and those +required of the plugins you're running. + +Contributions supporting other cache stores are welcome! + ## Containerization The example Backstage architecture shown above would Dockerize into three diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index dbdd1fd184..d37cffd680 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -34,6 +34,8 @@ backend: #ca: # if you have a CA file and want to verify it you can uncomment this section # $file: /ca/server.crt {{/if}} + cache: + store: memory # workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir integrations: diff --git a/packages/create-app/templates/default-app/packages/backend/src/index.ts b/packages/create-app/templates/default-app/packages/backend/src/index.ts index 80dc6230a6..aebd034aae 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/index.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/index.ts @@ -13,6 +13,7 @@ import { getRootLogger, useHotMemoize, notFoundHandler, + CacheManager, SingleConnectionDatabaseManager, SingleHostDiscovery, UrlReaders, @@ -34,11 +35,13 @@ function makeCreateEnv(config: Config) { root.info(`Created UrlReader ${reader}`); const databaseManager = SingleConnectionDatabaseManager.fromConfig(config); + const cacheManager = CacheManager.fromConfig(config); return (plugin: string): PluginEnvironment => { const logger = root.child({ type: 'plugin', plugin }); const database = databaseManager.forPlugin(plugin); - return { logger, database, config, reader, discovery }; + const cache = cacheManager.forPlugin(plugin); + return { logger, database, cache, config, reader, discovery }; }; } diff --git a/packages/create-app/templates/default-app/packages/backend/src/types.ts b/packages/create-app/templates/default-app/packages/backend/src/types.ts index 757a0e5acf..e5bfff2e1f 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/types.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/types.ts @@ -1,6 +1,7 @@ import { Logger } from 'winston'; import { Config } from '@backstage/config'; import { + PluginCacheManager, PluginDatabaseManager, PluginEndpointDiscovery, UrlReader, @@ -9,6 +10,7 @@ import { export type PluginEnvironment = { logger: Logger; database: PluginDatabaseManager; + cache: PluginCacheManager; config: Config; reader: UrlReader discovery: PluginEndpointDiscovery;