From 9bb27e7ab4cad21e2d1abe3746989ac5b7cd9c80 Mon Sep 17 00:00:00 2001 From: Ariel Gentile Date: Mon, 5 Feb 2024 17:41:31 -0300 Subject: [PATCH] feat: add caching --- src/anoncreds/DidWebAnonCredsRegistry.ts | 117 ++++++++++++++++++++++- test/schema.test.ts | 2 +- 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/src/anoncreds/DidWebAnonCredsRegistry.ts b/src/anoncreds/DidWebAnonCredsRegistry.ts index 8d20cbd..33bb062 100644 --- a/src/anoncreds/DidWebAnonCredsRegistry.ts +++ b/src/anoncreds/DidWebAnonCredsRegistry.ts @@ -17,18 +17,48 @@ import { RegisterSchemaOptions, RegisterSchemaReturn, } from '@credo-ts/anoncreds' -import { AgentContext, DidsApi } from '@credo-ts/core' +import { AgentContext, CacheModuleConfig, DidsApi } from '@credo-ts/core' import { parse } from 'did-resolver' import { parseUrl } from 'query-string' import { AnonCredsResourceResolutionResult } from './AnonCredsResourceResolutionResult' import { calculateResourceId, verifyResourceId } from './utils' +export interface CacheSettings { + allowCaching: boolean + cacheDurationInSeconds: number +} + export class DidWebAnonCredsRegistry implements AnonCredsRegistry { public readonly methodName = 'web' public readonly supportedIdentifier = /^did:web:[_a-z0-9.%A-]*/ + private cacheSettings: CacheSettings + + public constructor(options: { cacheOptions?: CacheSettings }) { + this.cacheSettings = options.cacheOptions ?? { allowCaching: true, cacheDurationInSeconds: 300 } + } + public async getSchema(agentContext: AgentContext, schemaId: string): Promise { + const cacheKey = `anoncreds:schema:${schemaId}` + + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + + const cachedObject = await cache.get(agentContext, cacheKey) + + if (cachedObject) { + return { + schema: cachedObject.schema, + schemaId, + schemaMetadata: cachedObject.schemaMetadata, + resolutionMetadata: { + ...cachedObject.resolutionMetadata, + servedFromCache: true, + }, + } + } + } try { const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, schemaId) @@ -40,6 +70,20 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { throw new Error('Wrong resource Id') } + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + await cache.set( + agentContext, + cacheKey, + { + resolutionMetadata: {}, + schema, + schemaMetadata, + }, + this.cacheSettings.cacheDurationInSeconds + ) + } + return { schemaId, schema, @@ -55,7 +99,7 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { } } } catch (error) { - console.log(`error: ${error}`) + agentContext.config.logger.debug(`error: ${error}`) return { resolutionMetadata: { error: 'invalid' }, schemaMetadata: {}, @@ -83,6 +127,27 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { agentContext: AgentContext, credentialDefinitionId: string ): Promise { + const cacheKey = `anoncreds:credentialDefinition:${credentialDefinitionId}` + + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + + const cachedObject = await cache.get(agentContext, cacheKey) + + if (cachedObject) { + return { + credentialDefinition: cachedObject.credentialDefinition, + credentialDefinitionId, + credentialDefinitionMetadata: cachedObject.credentialDefinitionMetadata, + resolutionMetadata: { + ...cachedObject.resolutionMetadata, + servedFromCache: true, + }, + } + } + } + + try { const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, credentialDefinitionId) if (response.status === 200) { @@ -94,6 +159,20 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { throw new Error('Wrong resource Id') } + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + await cache.set( + agentContext, + cacheKey, + { + resolutionMetadata: {}, + credentialDefinition, + credentialDefinitionMetadata, + }, + this.cacheSettings.cacheDurationInSeconds + ) + } + return { credentialDefinitionId, credentialDefinition, @@ -141,6 +220,26 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { agentContext: AgentContext, revocationRegistryDefinitionId: string ): Promise { + const cacheKey = `anoncreds:revocationRegistryDefinition:${revocationRegistryDefinitionId}` + + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + + const cachedObject = await cache.get(agentContext, cacheKey) + + if (cachedObject) { + return { + revocationRegistryDefinition: cachedObject.revocationRegistryDefinition, + revocationRegistryDefinitionId, + revocationRegistryDefinitionMetadata: cachedObject.revocationRegistryDefinitionMetadata, + resolutionMetadata: { + ...cachedObject.resolutionMetadata, + servedFromCache: true, + }, + } + } + } + try { const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, revocationRegistryDefinitionId) if (response.status === 200) { @@ -152,6 +251,20 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry { throw new Error('Wrong resource Id') } + if (this.cacheSettings.allowCaching) { + const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache + await cache.set( + agentContext, + cacheKey, + { + resolutionMetadata: {}, + revocationRegistryDefinition, + revocationRegistryDefinitionMetadata, + }, + this.cacheSettings.cacheDurationInSeconds + ) + } + return { revocationRegistryDefinitionId, revocationRegistryDefinition, diff --git a/test/schema.test.ts b/test/schema.test.ts index 94058fc..97b8246 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -31,7 +31,7 @@ describe.skip('Schema', () => { jest.spyOn(didsApiMock, 'resolveDidDocument').mockResolvedValue(JsonTransformer.fromJSON(didDocument1, DidDocument)) - const registry = new DidWebAnonCredsRegistry() + const registry = new DidWebAnonCredsRegistry({}) const schemaResponse = await registry.getSchema( getAgentContext(),