Skip to content

Commit

Permalink
chore(kv): create abstract KvArnsStore to handle the hashing keys f…
Browse files Browse the repository at this point in the history
…or arns in cache

This is to avoid doing it in the composite resolver
  • Loading branch information
dtfiedler committed Sep 9, 2024
1 parent 037417e commit 3b09c9e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/init/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { AoIORead } from '@ar.io/sdk';
import { CompositeArNSResolver } from '../resolution/composite-arns-resolver.js';
import { RedisKvStore } from '../store/redis-kv-store.js';
import { NodeKvStore } from '../store/node-kv-store.js';
import { KvArnsStore } from '../store/kv-arns-store.js';

const supportedResolvers = ['on-demand', 'gateway'] as const;
export type ArNSResolverType = (typeof supportedResolvers)[number];
Expand Down Expand Up @@ -68,7 +69,7 @@ export const createArNSResolver = ({
networkProcess,
}: {
log: Logger;
cache: KVBufferStore;
cache: KvArnsStore;
resolutionOrder: (ArNSResolverType | string)[];
trustedGatewayUrl?: string;
networkProcess?: AoIORead;
Expand Down
13 changes: 4 additions & 9 deletions src/resolution/composite-arns-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import winston from 'winston';
import { KVBufferStore, NameResolution, NameResolver } from '../types.js';
import * as metrics from '../metrics.js';
import { KvArnsStore } from '../store/kv-arns-store.js';

export class CompositeArNSResolver implements NameResolver {
private log: winston.Logger;
Expand All @@ -31,22 +32,18 @@ export class CompositeArNSResolver implements NameResolver {
}: {
log: winston.Logger;
resolvers: NameResolver[];
cache: KVBufferStore;
cache: KvArnsStore;
}) {
this.log = log.child({ class: this.constructor.name });
this.resolvers = resolvers;
this.cache = cache;
}

private hashKey(key: string): string {
return `arns|${key}`;
}

async resolve(name: string): Promise<NameResolution> {
this.log.info('Resolving name...', { name });

try {
const cachedResolutionBuffer = await this.cache.get(this.hashKey(name));
const cachedResolutionBuffer = await this.cache.get(name);
if (cachedResolutionBuffer) {
const cachedResolution: NameResolution = JSON.parse(
cachedResolutionBuffer.toString(),
Expand All @@ -73,9 +70,7 @@ export class CompositeArNSResolver implements NameResolver {
});
const resolution = await resolver.resolve(name);
if (resolution.resolvedId !== undefined) {
const hashKey = this.hashKey(name);
const resolutionBuffer = Buffer.from(JSON.stringify(resolution));
await this.cache.set(hashKey, resolutionBuffer);
await this.cache.set(name, Buffer.from(JSON.stringify(resolution)));
this.log.info('Resolved name', { name, resolution });
return resolution;
}
Expand Down
51 changes: 51 additions & 0 deletions src/store/kv-arns-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* AR.IO Gateway
* Copyright (C) 2022-2023 Permanent Data Solutions, Inc. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { KVBufferStore } from '../types.js';

export class KvArnsStore implements KVBufferStore {
private kvBufferStore: KVBufferStore;

constructor({ kvBufferStore }: { kvBufferStore: KVBufferStore }) {
this.kvBufferStore = kvBufferStore;
}

private hashKey(key: string): string {
return `arns|${key}`;
}

async get(key: string): Promise<Buffer | undefined> {
return this.kvBufferStore.get(this.hashKey(key));
}

async set(key: string, value: Buffer): Promise<void> {
return this.kvBufferStore.set(this.hashKey(key), value);
}

async has(key: string): Promise<boolean> {
return this.kvBufferStore.has(this.hashKey(key));
}

async del(key: string): Promise<void> {
return this.kvBufferStore.del(this.hashKey(key));
}

async close(): Promise<void> {
return this.kvBufferStore.close();
}
}
15 changes: 9 additions & 6 deletions src/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { connect } from '@permaweb/aoconnect';
import { DataContentAttributeImporter } from './workers/data-content-attribute-importer.js';
import { SignatureFetcher } from './data/signature-fetcher.js';
import { SQLiteWalCleanupWorker } from './workers/sqlite-wal-cleanup-worker.js';
import { KvArnsStore } from './store/kv-arns-store.js';

process.on('uncaughtException', (error) => {
metrics.uncaughtExceptionCounter.inc();
Expand Down Expand Up @@ -550,12 +551,14 @@ export const manifestPathResolver = new StreamingManifestPathResolver({
log,
});

export const arnsResolverCache = createArNSKvStore({
log,
type: config.ARNS_CACHE_TYPE,
redisUrl: config.REDIS_CACHE_URL,
ttlSeconds: config.ARNS_CACHE_TTL_SECONDS,
maxKeys: config.ARNS_CACHE_MAX_KEYS,
export const arnsResolverCache = new KvArnsStore({
kvBufferStore: createArNSKvStore({
log,
type: config.ARNS_CACHE_TYPE,
redisUrl: config.REDIS_CACHE_URL,
ttlSeconds: config.ARNS_CACHE_TTL_SECONDS,
maxKeys: config.ARNS_CACHE_MAX_KEYS,
}),
});

export const nameResolver = createArNSResolver({
Expand Down

0 comments on commit 3b09c9e

Please sign in to comment.