make CacheManager.forPlugin return a CacheService directly

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2024-08-30 15:47:11 +02:00
parent 140a61ab8d
commit 15e3e073d6
8 changed files with 63 additions and 59 deletions
+7
View File
@@ -4,7 +4,14 @@
**BREAKING**: Simplifications and cleanup as part of the Backend System 1.0 work.
For the `/database` subpath exports:
- The deprecated `dropDatabase` function has now been removed, without replacement.
- The deprecated `LegacyRootDatabaseService` type has now been removed.
- The return type from `DatabaseManager.forPlugin` is now directly a `DatabaseService`, as arguably expected.
- `DatabaseManager.forPlugin` now requires the `deps` argument, with the logger and lifecycle services.
For the `/cache` subpath exports:
- The `PluginCacheManager` type has been removed. You can still import it from `@backstage/backend-common`, but it's deprecated there, and you should move off of that package by migrating fully to the new backend system.
- Accordingly, `CacheManager.forPlugin` immediately returns a `CacheService` instead of a `PluginCacheManager`. The outcome of this is that you no longer need to make the extra `.getClient()` call. The old `CacheManager` with the old behavior still exists on `@backstage/backend-common`, but the above recommendations apply.
@@ -23,10 +23,7 @@ import { HostDiscovery as _HostDiscovery } from '../../../backend-defaults/src/e
import { CacheManager as _CacheManager } from '../../../backend-defaults/src/entrypoints/cache/CacheManager';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import {
type PluginCacheManager as _PluginCacheManager,
type CacheManagerOptions as _CacheManagerOptions,
} from '../../../backend-defaults/src/entrypoints/cache/types';
import { type CacheManagerOptions as _CacheManagerOptions } from '../../../backend-defaults/src/entrypoints/cache/types';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import {
@@ -48,6 +45,7 @@ import {
PluginMetadataService,
DatabaseService,
LoggerService,
RootConfigService,
} from '@backstage/backend-plugin-api';
export * from './hot';
@@ -133,7 +131,31 @@ export { HostDiscovery as SingleHostDiscovery };
* @public
* @deprecated Use `CacheManager` from the `@backstage/backend-defaults` package instead
*/
export class CacheManager extends _CacheManager {}
export class CacheManager {
/**
* Creates a new {@link CacheManager} instance by reading from the `backend`
* config section, specifically the `.cache` key.
*
* @param config - The loaded application configuration.
*/
static fromConfig(
config: RootConfigService,
options: CacheManagerOptions = {},
): CacheManager {
return new CacheManager(_CacheManager.fromConfig(config, options));
}
private constructor(private readonly _impl: _CacheManager) {}
forPlugin(pluginId: string): PluginCacheManager {
return {
getClient: options => {
const result = this._impl.forPlugin(pluginId);
return options ? result.withOptions(options) : result;
},
};
}
}
/**
* @public
@@ -145,7 +167,9 @@ export type CacheManagerOptions = _CacheManagerOptions;
* @public
* @deprecated Use `PluginCacheManager` from the `@backstage/backend-defaults` package instead
*/
export type PluginCacheManager = _PluginCacheManager;
export type PluginCacheManager = {
getClient(options?: CacheServiceOptions): CacheService;
};
/**
* @public
@@ -4,14 +4,13 @@
```ts
import { CacheService } from '@backstage/backend-plugin-api';
import { CacheServiceOptions } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
import { RootConfigService } from '@backstage/backend-plugin-api';
import { ServiceFactory } from '@backstage/backend-plugin-api';
// @public
export class CacheManager {
forPlugin(pluginId: string): PluginCacheManager;
forPlugin(pluginId: string): CacheService;
static fromConfig(
config: RootConfigService,
options?: CacheManagerOptions,
@@ -31,11 +30,5 @@ export const cacheServiceFactory: ServiceFactory<
'singleton'
>;
// @public (undocumented)
export interface PluginCacheManager {
// (undocumented)
getClient(options?: CacheServiceOptions): CacheService;
}
// (No @packageDocumentation comment for this package)
```
@@ -52,10 +52,10 @@ describe('CacheManager integration', () => {
}),
);
manager.forPlugin('p1').getClient();
manager.forPlugin('p1').getClient({ defaultTtl: 200 });
manager.forPlugin('p2').getClient();
manager.forPlugin('p3').getClient({});
manager.forPlugin('p1');
manager.forPlugin('p1').withOptions({ defaultTtl: 200 });
manager.forPlugin('p2');
manager.forPlugin('p3').withOptions({});
if (store === 'redis') {
// eslint-disable-next-line jest/no-conditional-expect
@@ -80,9 +80,11 @@ describe('CacheManager integration', () => {
}),
);
const plugin1 = manager.forPlugin('p1').getClient();
const plugin2a = manager.forPlugin('p2').getClient();
const plugin2b = manager.forPlugin('p2').getClient({ defaultTtl: 2000 });
const plugin1 = manager.forPlugin('p1');
const plugin2a = manager.forPlugin('p2');
const plugin2b = manager
.forPlugin('p2')
.withOptions({ defaultTtl: 2000 });
await plugin1.set('a', 'plugin1');
await plugin2a.set('a', 'plugin2a');
@@ -114,9 +116,9 @@ describe('CacheManager integration', () => {
}),
).forPlugin('p');
const defaultClient = manager.getClient();
const numberOverrideClient = manager.getClient({ defaultTtl: 400 });
const durationOverrideClient = manager.getClient({
const defaultClient = manager;
const numberOverrideClient = manager.withOptions({ defaultTtl: 400 });
const durationOverrideClient = manager.withOptions({
defaultTtl: { milliseconds: 400 },
});
@@ -15,17 +15,14 @@
*/
import {
CacheService,
CacheServiceOptions,
LoggerService,
RootConfigService,
} from '@backstage/backend-plugin-api';
import Keyv from 'keyv';
import { DefaultCacheClient } from './CacheClient';
import {
CacheManagerOptions,
PluginCacheManager,
ttlToMilliseconds,
} from './types';
import { CacheManagerOptions, ttlToMilliseconds } from './types';
import { durationToMilliseconds } from '@backstage/types';
type StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv;
@@ -129,24 +126,16 @@ export class CacheManager {
* @param pluginId - The plugin that the cache manager should be created for.
* Plugin names should be unique.
*/
forPlugin(pluginId: string): PluginCacheManager {
return {
getClient: (defaultOptions = {}) => {
const clientFactory = (options: CacheServiceOptions) => {
const ttl = options.defaultTtl ?? this.defaultTtl;
return this.getClientWithTtl(
pluginId,
ttl !== undefined ? ttlToMilliseconds(ttl) : undefined,
);
};
return new DefaultCacheClient(
clientFactory(defaultOptions),
clientFactory,
defaultOptions,
);
},
forPlugin(pluginId: string): CacheService {
const clientFactory = (options: CacheServiceOptions) => {
const ttl = options.defaultTtl ?? this.defaultTtl;
return this.getClientWithTtl(
pluginId,
ttl !== undefined ? ttlToMilliseconds(ttl) : undefined,
);
};
return new DefaultCacheClient(clientFactory({}), clientFactory, {});
}
private getClientWithTtl(pluginId: string, ttl: number | undefined): Keyv {
@@ -40,6 +40,6 @@ export const cacheServiceFactory = createServiceFactory({
return CacheManager.fromConfig(config, { logger });
},
async factory({ plugin }, manager) {
return manager.forPlugin(plugin.getId()).getClient();
return manager.forPlugin(plugin.getId());
},
});
+1 -1
View File
@@ -16,4 +16,4 @@
export { cacheServiceFactory } from './cacheServiceFactory';
export { CacheManager } from './CacheManager';
export type { CacheManagerOptions, PluginCacheManager } from './types';
export type { CacheManagerOptions } from './types';
@@ -15,10 +15,6 @@
*/
import { LoggerService } from '@backstage/backend-plugin-api';
import {
CacheService,
CacheServiceOptions,
} from '@backstage/backend-plugin-api';
import { HumanDuration, durationToMilliseconds } from '@backstage/types';
/**
@@ -39,13 +35,6 @@ export type CacheManagerOptions = {
onError?: (err: Error) => void;
};
/**
* @public
*/
export interface PluginCacheManager {
getClient(options?: CacheServiceOptions): CacheService;
}
export function ttlToMilliseconds(ttl: number | HumanDuration): number {
return typeof ttl === 'number' ? ttl : durationToMilliseconds(ttl);
}