diff --git a/src/cache/BasicSortKeyCache.ts b/src/cache/BasicSortKeyCache.ts new file mode 100644 index 0000000..ad8897c --- /dev/null +++ b/src/cache/BasicSortKeyCache.ts @@ -0,0 +1,71 @@ +import { CacheKey, PruneStats, SortKeyCacheResult } from './SortKeyCache'; + +/** + * A cache that stores its values per dedicated key and sort key. + * A sort key is a value that the SmartWeave protocol is using + * to sort contract transactions ({@link LexicographicalInteractionsSorter}. + * + * All values should be stored in a lexicographical order (per key) - + * sorted by the sort key. + */ +export interface BasicSortKeyCache { + getLessOrEqual(key: string, sortKey: string): Promise | null>; + + /** + * returns value stored for a given key and last sortKey + */ + getLast(key: string): Promise | null>; + + /** + * returns last cached sort key - takes all keys into account + */ + getLastSortKey(): Promise; + + /** + * returns value for the key and exact sortKey + */ + get(cacheKey: CacheKey): Promise | null>; + + /** + * puts new value in cache under given {@link CacheKey.key} and {@link CacheKey.sortKey}. + */ + put(cacheKey: CacheKey, value: V): Promise; + + /** + * removes all data stored under a specified key + */ + delete(key: string): Promise; + + open(): Promise; + + close(): Promise; + + begin(): Promise; + + rollback(): Promise; + + commit(): Promise; + + /** + * used mostly for debugging, allows to dump the current content cache + * It's slow. + */ + dump(): Promise; // eslint-disable-line @typescript-eslint/no-explicit-any + + /** + * returns underlying storage (LevelDB, LMDB, sqlite...) + * - useful for performing low-level operations + */ + storage(): S; + + /** + * leaves n-latest (i.e. with latest (in lexicographic order) sort keys) + * entries for each cached key + * + * @param entriesStored - how many latest entries should be left + * for each cached key + * + * @retun PruneStats if getting them doesn't introduce a delay, null otherwise + */ + prune(entriesStored: number): Promise; +} diff --git a/src/cache/SortKeyCache.ts b/src/cache/SortKeyCache.ts index 20142ef..5ea0d6d 100644 --- a/src/cache/SortKeyCache.ts +++ b/src/cache/SortKeyCache.ts @@ -1,68 +1,26 @@ import { SortKeyCacheRangeOptions } from './SortKeyCacheRangeOptions'; +import { BasicSortKeyCache } from './BasicSortKeyCache'; /** - * A cache that stores its values per dedicated key and sort key. - * A sort key is a value that the SmartWeave protocol is using - * to sort contract transactions ({@link LexicographicalInteractionsSorter}. + * Key-value cache storage. + * Just as {@link BasicSortKeyCache}, items are stored + * in lexicographical order using by sort key. * - * All values should be stored in a lexicographical order (per key) - - * sorted by the sort key. + * In addition, this interface provide functionality related to + * fetching keys and values using range options. {@link SortKeyCacheRangeOptions} */ -export interface SortKeyCache { - getLessOrEqual(key: string, sortKey: string): Promise | null>; - - /** - * returns value stored for a given key and last sortKey - */ - getLast(key: string): Promise | null>; - - /** - * returns last cached sort key - takes all keys into account - */ - getLastSortKey(): Promise; - - /** - * returns value for the key and exact sortKey - */ - get(cacheKey: CacheKey): Promise | null>; - - /** - * puts new value in cache under given {@link CacheKey.key} and {@link CacheKey.sortKey}. - */ - put(cacheKey: CacheKey, value: V): Promise; - +export interface SortKeyCache extends BasicSortKeyCache { /** * deletes value in cache under given {@link CacheKey.key} from {@link CacheKey.sortKey}. * the value will be still available if fetched using a lower sortKey */ del(cacheKey: CacheKey): Promise; - /** - * removes all data stored under a specified key - */ - delete(key: string): Promise; - /** * executes a list of stacked operations */ batch(opStack: BatchDBOp[]); - open(): Promise; - - close(): Promise; - - begin(): Promise; - - rollback(): Promise; - - commit(): Promise; - - /** - * used mostly for debugging, allows to dump the current content cache - * It's slow. - */ - dump(): Promise; // eslint-disable-line @typescript-eslint/no-explicit-any - /** * Returns keys for a specified range */ @@ -72,23 +30,6 @@ export interface SortKeyCache { * Returns a key value map for a specified range */ kvMap(sortKey: string, options?: SortKeyCacheRangeOptions): Promise>; - - /** - * returns underlying storage (LevelDB, LMDB, sqlite...) - * - useful for performing low-level operations - */ - storage(): S; - - /** - * leaves n-latest (i.e. with latest (in lexicographic order) sort keys) - * entries for each cached key - * - * @param entriesStored - how many latest entries should be left - * for each cached key - * - * @retun PruneStats if getting them doesn't introduce a delay, null otherwise - */ - prune(entriesStored: number): Promise; } export interface PruneStats { @@ -107,11 +48,13 @@ export class SortKeyCacheResult { } export declare type BatchDBOp = PutBatch | DelBatch; + export interface PutBatch { type: 'put'; key: CacheKey; value: V; } + export interface DelBatch { type: 'del'; key: string; diff --git a/src/cache/SortKeyCacheRangeOptions.ts b/src/cache/SortKeyCacheRangeOptions.ts index 082f78a..bdd581d 100644 --- a/src/cache/SortKeyCacheRangeOptions.ts +++ b/src/cache/SortKeyCacheRangeOptions.ts @@ -1,3 +1,10 @@ +/** + * Range option for fetching items from kv storage {@link SortKeyCache} + * @param gte - greater than equals + * @param lt - less than + * @param reverse - reverses the order + * @param limit - limits output elements + */ export interface SortKeyCacheRangeOptions { gte?: string; lt?: string; diff --git a/src/core/Warp.ts b/src/core/Warp.ts index cf42232..e2b2438 100644 --- a/src/core/Warp.ts +++ b/src/core/Warp.ts @@ -33,6 +33,7 @@ import { DEFAULT_LEVEL_DB_LOCATION, WARP_GW_URL } from './WarpFactory'; import { LevelDbCache } from '../cache/impl/LevelDbCache'; import { SourceData } from '../contract/deploy/Source'; import { BundlerSigner, DataItem } from '../contract/deploy/DataItem'; +import { BasicSortKeyCache } from '../cache/BasicSortKeyCache'; export type WarpEnvironment = 'local' | 'testnet' | 'mainnet' | 'custom'; export type KVStorageFactory = (contractTxId: string) => SortKeyCache; @@ -87,7 +88,7 @@ export class Warp { static builder( arweave: Arweave, - stateCache: SortKeyCache>, + stateCache: BasicSortKeyCache>, environment: WarpEnvironment ): WarpBuilder { return new WarpBuilder(arweave, stateCache, environment); @@ -138,12 +139,12 @@ export class Warp { return new PstContractImpl(contractTxId, this); } - useStateCache(stateCache: SortKeyCache>): Warp { + useStateCache(stateCache: BasicSortKeyCache>): Warp { this.stateEvaluator.setCache(stateCache); return this; } - useContractCache(definition: SortKeyCache>, src: SortKeyCache): Warp { + useContractCache(definition: BasicSortKeyCache>, src: SortKeyCache): Warp { this.definitionLoader.setSrcCache(src); this.definitionLoader.setCache(definition); return this; diff --git a/src/core/WarpBuilder.ts b/src/core/WarpBuilder.ts index 72213fd..821412c 100644 --- a/src/core/WarpBuilder.ts +++ b/src/core/WarpBuilder.ts @@ -12,9 +12,9 @@ import { InteractionsLoader } from './modules/InteractionsLoader'; import { StateEvaluator, EvalStateResult } from './modules/StateEvaluator'; import { WarpEnvironment, Warp } from './Warp'; import { CacheOptions, GatewayOptions } from './WarpFactory'; -import { SortKeyCache } from '../cache/SortKeyCache'; import { LevelDbCache } from '../cache/impl/LevelDbCache'; import { ContractCache, SrcCache } from './ContractDefinition'; +import { BasicSortKeyCache } from '../cache/BasicSortKeyCache'; export class WarpBuilder { private _definitionLoader?: DefinitionLoader; @@ -24,7 +24,7 @@ export class WarpBuilder { constructor( private readonly _arweave: Arweave, - private readonly _stateCache: SortKeyCache>, + private readonly _stateCache: BasicSortKeyCache>, private readonly _environment: WarpEnvironment = 'custom' ) {} diff --git a/src/core/modules/DefinitionLoader.ts b/src/core/modules/DefinitionLoader.ts index d9c4d5c..86b2bcc 100644 --- a/src/core/modules/DefinitionLoader.ts +++ b/src/core/modules/DefinitionLoader.ts @@ -1,7 +1,7 @@ import { ContractCache, ContractDefinition, ContractSource, SrcCache } from '../../core/ContractDefinition'; import { GwTypeAware } from './InteractionsLoader'; -import { SortKeyCache } from '../../cache/SortKeyCache'; import { WarpAware } from '../Warp'; +import { BasicSortKeyCache } from '../../cache/BasicSortKeyCache'; /** * Implementors of this interface are responsible for loading contract's definitions - @@ -13,12 +13,12 @@ export interface DefinitionLoader extends GwTypeAware, WarpAware { loadContractSource(srcTxId: string): Promise; - setCache(cache: SortKeyCache>): void; + setCache(cache: BasicSortKeyCache>): void; // Cache for storing common source code or binaries - setSrcCache(cacheSrc?: SortKeyCache): void; + setSrcCache(cacheSrc?: BasicSortKeyCache): void; - getCache(): SortKeyCache>; + getCache(): BasicSortKeyCache>; - getSrcCache(): SortKeyCache; + getSrcCache(): BasicSortKeyCache; } diff --git a/src/core/modules/StateEvaluator.ts b/src/core/modules/StateEvaluator.ts index 51061c9..da1e652 100644 --- a/src/core/modules/StateEvaluator.ts +++ b/src/core/modules/StateEvaluator.ts @@ -1,7 +1,8 @@ -import { SortKeyCache, SortKeyCacheResult } from '../../cache/SortKeyCache'; +import { SortKeyCacheResult } from '../../cache/SortKeyCache'; import { ExecutionContext } from '../ExecutionContext'; import { GQLNodeInterface } from '../../legacy/gqlResult'; import { SourceType } from './impl/WarpGatewayInteractionsLoader'; +import { BasicSortKeyCache } from '../../cache/BasicSortKeyCache'; /** * Implementors of this class are responsible for evaluating contract's state @@ -87,9 +88,9 @@ export interface StateEvaluator { lastCachedSortKey(): Promise; - setCache(cache: SortKeyCache>): void; + setCache(cache: BasicSortKeyCache>): void; - getCache(): SortKeyCache>; + getCache(): BasicSortKeyCache>; } export class EvalStateResult { diff --git a/src/core/modules/impl/CacheableStateEvaluator.ts b/src/core/modules/impl/CacheableStateEvaluator.ts index 19b4a62..64f0aa3 100644 --- a/src/core/modules/impl/CacheableStateEvaluator.ts +++ b/src/core/modules/impl/CacheableStateEvaluator.ts @@ -1,5 +1,5 @@ import Arweave from 'arweave'; -import { CacheKey, SortKeyCache, SortKeyCacheResult } from '../../../cache/SortKeyCache'; +import { CacheKey, SortKeyCacheResult } from '../../../cache/SortKeyCache'; import { ExecutionContext } from '../../../core/ExecutionContext'; import { ExecutionContextModifier } from '../../../core/ExecutionContextModifier'; import { GQLNodeInterface } from '../../../legacy/gqlResult'; @@ -9,6 +9,7 @@ import { EvalStateResult } from '../StateEvaluator'; import { DefaultStateEvaluator } from './DefaultStateEvaluator'; import { HandlerApi } from './HandlerExecutorFactory'; import { genesisSortKey } from './LexicographicalInteractionsSorter'; +import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; /** * An implementation of DefaultStateEvaluator that adds caching capabilities. @@ -23,7 +24,7 @@ export class CacheableStateEvaluator extends DefaultStateEvaluator { constructor( arweave: Arweave, - private cache: SortKeyCache>, + private cache: BasicSortKeyCache>, executionContextModifiers: ExecutionContextModifier[] = [] ) { super(arweave, executionContextModifiers); @@ -224,11 +225,11 @@ export class CacheableStateEvaluator extends DefaultStateEvaluator { return await this.cache.getLastSortKey(); } - setCache(cache: SortKeyCache>): void { + setCache(cache: BasicSortKeyCache>): void { this.cache = cache; } - getCache(): SortKeyCache> { + getCache(): BasicSortKeyCache> { return this.cache; } } diff --git a/src/core/modules/impl/ContractDefinitionLoader.ts b/src/core/modules/impl/ContractDefinitionLoader.ts index 05fe07b..ea78e8d 100644 --- a/src/core/modules/impl/ContractDefinitionLoader.ts +++ b/src/core/modules/impl/ContractDefinitionLoader.ts @@ -16,8 +16,8 @@ import { GW_TYPE } from '../InteractionsLoader'; import { TagsParser } from './TagsParser'; import { WasmSrc } from './wasm/WasmSrc'; import { Warp, WarpEnvironment } from '../../Warp'; -import { SortKeyCache } from '../../../cache/SortKeyCache'; import { Transaction } from '../../../utils/types/arweave-types'; +import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; export class ContractDefinitionLoader implements DefinitionLoader { private readonly logger = LoggerFactory.INST.create('ContractDefinitionLoader'); @@ -147,20 +147,20 @@ export class ContractDefinitionLoader implements DefinitionLoader { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - setCache(cache: SortKeyCache>): void { + setCache(cache: BasicSortKeyCache>): void { throw new Error('No cache implemented for this loader'); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - setSrcCache(cache: SortKeyCache): void { + setSrcCache(cache: BasicSortKeyCache): void { throw new Error('No cache implemented for this loader'); } - getCache(): SortKeyCache> { + getCache(): BasicSortKeyCache> { throw new Error('No cache implemented for this loader'); } - getSrcCache(): SortKeyCache { + getSrcCache(): BasicSortKeyCache { throw new Error('No cache implemented for this loader'); } diff --git a/src/core/modules/impl/DefaultStateEvaluator.ts b/src/core/modules/impl/DefaultStateEvaluator.ts index fe4cf47..4046afe 100644 --- a/src/core/modules/impl/DefaultStateEvaluator.ts +++ b/src/core/modules/impl/DefaultStateEvaluator.ts @@ -1,6 +1,6 @@ import Arweave from 'arweave'; -import { SortKeyCache, SortKeyCacheResult } from '../../../cache/SortKeyCache'; +import { SortKeyCacheResult } from '../../../cache/SortKeyCache'; import { InteractionCall } from '../../ContractCallRecord'; import { ExecutionContext } from '../../../core/ExecutionContext'; import { ExecutionContextModifier } from '../../../core/ExecutionContextModifier'; @@ -12,6 +12,7 @@ import { EvalStateResult, StateEvaluator } from '../StateEvaluator'; import { ContractInteraction, HandlerApi, InteractionResult } from './HandlerExecutorFactory'; import { TagsParser } from './TagsParser'; import { VrfPluginFunctions } from '../../WarpPlugin'; +import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; type EvaluationProgressInput = { contractTxId: string; @@ -396,9 +397,9 @@ export abstract class DefaultStateEvaluator implements StateEvaluator { abstract lastCachedSortKey(): Promise; - abstract setCache(cache: SortKeyCache>): void; + abstract setCache(cache: BasicSortKeyCache>): void; - abstract getCache(): SortKeyCache>; + abstract getCache(): BasicSortKeyCache>; } function canBeCached(tx: GQLNodeInterface): boolean { diff --git a/src/core/modules/impl/WarpGatewayContractDefinitionLoader.ts b/src/core/modules/impl/WarpGatewayContractDefinitionLoader.ts index cebb5e1..40c5dc1 100644 --- a/src/core/modules/impl/WarpGatewayContractDefinitionLoader.ts +++ b/src/core/modules/impl/WarpGatewayContractDefinitionLoader.ts @@ -11,9 +11,10 @@ import { DefinitionLoader } from '../DefinitionLoader'; import { WasmSrc } from './wasm/WasmSrc'; import { Warp, WarpEnvironment } from '../../Warp'; import { TagsParser } from './TagsParser'; -import { CacheKey, SortKeyCache, SortKeyCacheResult } from '../../../cache/SortKeyCache'; +import { CacheKey, SortKeyCacheResult } from '../../../cache/SortKeyCache'; import { Transaction } from '../../../utils/types/arweave-types'; import { getJsonResponse, stripTrailingSlash } from '../../../utils/utils'; +import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; /** * An extension to {@link ContractDefinitionLoader} that makes use of @@ -32,8 +33,8 @@ export class WarpGatewayContractDefinitionLoader implements DefinitionLoader { constructor( arweave: Arweave, - private definitionCache: SortKeyCache>, - private srcCache: SortKeyCache, + private definitionCache: BasicSortKeyCache>, + private srcCache: BasicSortKeyCache, private readonly env: WarpEnvironment ) { this.contractDefinitionLoader = new ContractDefinitionLoader(arweave, env); @@ -102,19 +103,19 @@ export class WarpGatewayContractDefinitionLoader implements DefinitionLoader { return 'warp'; } - setCache(cache: SortKeyCache>): void { + setCache(cache: BasicSortKeyCache>): void { this.definitionCache = cache; } - setSrcCache(cacheSrc: SortKeyCache): void { + setSrcCache(cacheSrc: BasicSortKeyCache): void { this.srcCache = cacheSrc; } - getCache(): SortKeyCache> { + getCache(): BasicSortKeyCache> { return this.definitionCache; } - getSrcCache(): SortKeyCache { + getSrcCache(): BasicSortKeyCache { return this.srcCache; } diff --git a/src/index.ts b/src/index.ts index 83a4816..6fd22cb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export * from './logging/LoggerFactory'; export * from './logging/LoggerSettings'; export * from './logging/Benchmark'; +export * from './cache/BasicSortKeyCache'; export * from './cache/SortKeyCache'; export * from './cache/WarpCache'; export * from './cache/impl/LevelDbCache';