@ixily/activ
Version:
Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.
310 lines (293 loc) • 7.93 kB
text/typescript
import {
CacheStorageModule,
ICacheVia,
PreCacheModule,
deserializeDataTool,
serializeDataTool,
} from '../../'
import { contractDbVersion } from '../../../version-contract-db.json'
const EXPIRATION_FOR_STRATEGY = 3600 * 24 * 100 // 100 days
// structure of cache
export const cachePlusUpsert = async (
preCacheId: string,
key: string,
data: string,
expiration?: number,
): Promise<void> => {
PreCacheModule.getSlots(preCacheId).add(key, data)
try {
await CacheStorageModule.addData(key, data, expiration)
} catch (err) {
await CacheStorageModule.updateData(key, data, expiration)
}
}
export const cachePlusRemove = async (key: string) => {
await CacheStorageModule.removeData(key)
}
export const cachePlusRetrieve = async <T>(
preCacheId: string,
key: string,
): Promise<string | undefined> => {
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
const preCached = PreCacheModule.getSlots(preCacheId).get<string>(key)
// console.log('preCached:')
// console.log(preCached)
if (preCached !== undefined) {
return preCached
}
const data = await CacheStorageModule.getData(key)
// console.log('data:')
// console.log(data)
return data as string | undefined
// return (await CacheStorageModule.removeData(key)) as unknown as string
}
const getCacheKeyFromParameters = (parameters: any[]): string => {
const serialized = serializeDataTool([contractDbVersion, ...parameters])
return serialized
}
const cacheIn = <U>(
cachedFunctionName: string,
argsToIndex: any[],
): ((cache: U) => Promise<void>) => {
return async (cache: U): Promise<void> => {
const cacheKey = getCacheKeyFromParameters([
cachedFunctionName,
argsToIndex,
])
// console.log('cache:')
// console.log(cache)
const cacheValue = serializeDataTool(cache)
// console.log('cacheValue:')
// console.log(cacheValue)
await cachePlusUpsert(
'strategyChain',
cacheKey,
cacheValue,
EXPIRATION_FOR_STRATEGY,
)
}
}
const cacheOut = <U>(
cachedFunctionName: string,
argsToIndex: any[],
): (() => Promise<U | undefined>) => {
return async (): Promise<U | undefined> => {
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
// console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=')
const cacheKey = getCacheKeyFromParameters([
cachedFunctionName,
argsToIndex,
])
// console.log('cacheKey:')
// console.log(cacheKey)
const cacheValueStr = await cachePlusRetrieve('strategyChain', cacheKey)
// console.log('cacheValueStr:')
// console.log(cacheValueStr)
if (cacheValueStr === undefined) {
return undefined
}
const cacheValue = deserializeDataTool(cacheValueStr) as U
return cacheValue
}
}
// A => Arguments
// U => Cache or Result
const cacheVia = <U>(
cachedFunctionName: string,
argsToIndex: any[],
): ICacheVia<U> => {
return {
in: cacheIn<U>(cachedFunctionName, argsToIndex),
out: cacheOut<U>(cachedFunctionName, argsToIndex),
}
}
const recover = async <T>(via: ICacheVia<T>): Promise<T | undefined> => {
return via.out()
}
// R => Result
// C => Cache
// U => Cache or Result
const resultAfterStore = async <R, C, U extends R>(
via: ICacheVia<U>,
resultCache:
| R
| {
result: R
cache: C
},
prevCached: any,
): Promise<R> => {
// console.log('---------------TO CACHE----------------')
// console.log('resultCache:')
// console.log((resultCache as unknown as any).cache.cachedStrategy)
// throw new Error('check')
const resultAsCache = resultCache as {
result: R
cache: U
}
if (
resultAsCache.result !== undefined &&
resultAsCache.cache !== undefined
) {
// console.log('resultAsCache.cache:')
// console.log(resultAsCache.cache)
const toGoCache = resultAsCache.cache
if (serializeDataTool(toGoCache) !== serializeDataTool(prevCached)) {
await via.in(toGoCache)
}
return resultAsCache.result as R
} else {
const resultAsResult = resultCache as R
const toGoCache = resultAsResult as U
if (serializeDataTool(toGoCache) !== serializeDataTool(prevCached)) {
await via.in(toGoCache)
}
return resultAsResult as R
}
}
// R => Result
// C => Cache
// U => Cache or Result
const resultAfterStoreWithCache = async <R, C>(
via: ICacheVia<C>,
resultCache: {
result: R
cache: C
},
prevCached: any,
): Promise<{
result: R
cache: C
}> => {
// console.log('---------------TO CACHE----------------')
// console.log('resultCache.cache:')
// console.log(resultCache.cache)
const toGoCache = resultCache.cache
if (serializeDataTool(toGoCache) !== serializeDataTool(prevCached)) {
await via.in(toGoCache)
}
return resultCache
}
// R => Result
// C => Cache
// A => Arguments
const dynamicCached = async <R, C, A extends any[], U extends R>(
functionCachedIdentifier: string,
functionToBeCalled: (...args: A[number][any]) => Promise<
| R
| {
result: R
cache: C
}
>,
argumentsForGettingData: A,
argsToIndex: any[],
): Promise<R> => {
const via = cacheVia<U>(functionCachedIdentifier, argsToIndex)
const cached = await recover(via)
// console.log('---------------FROM CACHE----------------')
// console.log('cached:')
// console.log(cached)
// if (cached !== undefined) {
// throw new Error('check')
// }
const argumentsForGettingDataPlusCache = [
...argumentsForGettingData,
cached,
]
const resultCache = await functionToBeCalled(
...argumentsForGettingDataPlusCache,
)
return resultAfterStore<R, C, U>(via, resultCache, cached)
}
// R => Result
// C => Cache
// A => Arguments
const dynamicCachedWithCache = async <R, C, A extends any[]>(
functionCachedIdentifier: string,
functionToBeCalled: (...args: A[number][any]) => Promise<{
result: R
cache: C
}>,
argumentsForGettingData: A,
argsToIndex: any[],
): Promise<{
result: R
cache: C
}> => {
const via = cacheVia<C>(functionCachedIdentifier, argsToIndex)
const cached = await recover(via)
// console.log('---------------FROM CACHE----------------')
// console.log('cached:')
// console.log(cached)
// if (cached !== undefined) {
// throw new Error('check')
// }
const argumentsForGettingDataPlusCache = [
...argumentsForGettingData,
cached,
]
const resultCache = await functionToBeCalled(
...argumentsForGettingDataPlusCache,
)
return resultAfterStoreWithCache<R, C>(via, resultCache, cached)
}
/*
const STRIP_COMMENTS =
/(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/gm
const ARGUMENT_NAMES = /([^\s,]+)/g
type FunctionType = (...args: any[]) => Promise<unknown>
function getParamNames<F extends FunctionType>(func: F): string[] {
const fnStr = func.toString().replace(STRIP_COMMENTS, '')
let result: string[] | null = fnStr
.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')'))
.match(ARGUMENT_NAMES)
if (result === null) result = [] as string[]
return result as string[]
}
*/
export const dynamicCachedFunction = <R, C, A extends any[]>(
functionToBeCached: (...args: A[number][any]) => Promise<
| R
| {
result: R
cache: C
}
>,
argsToIndex: any[],
): ((...args: A[number][any]) => Promise<R>) => {
const fName = functionToBeCached.name
return async (...args: A[number][any]): Promise<R> => {
return dynamicCached(fName, functionToBeCached, args, argsToIndex)
}
}
export const dynamicCachedFunctionWithCache = <R, C, A extends any[]>(
functionToBeCached: (...args: A[number][any]) => Promise<{
result: R
cache: C
}>,
argsToIndex: any[],
): ((...args: A[number][any]) => Promise<{
result: R
cache: C
}>) => {
const fName = functionToBeCached.name
return async (
...args: A[number][any]
): Promise<{
result: R
cache: C
}> => {
return dynamicCachedWithCache(
fName,
functionToBeCached,
args,
argsToIndex,
)
}
}