-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce Link DB API (DAP-4685)
- Loading branch information
Showing
7 changed files
with
231 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
type MemoizedFunction<T, R> = (arg: T) => R | ||
|
||
export const memoize = | ||
<T, R>(fn: MemoizedFunction<T, R>, map = new Map<T, R | MemoizedFunction<T, R>>()) => | ||
(arg: T): R | MemoizedFunction<T, R> => { | ||
const inCache = map.has(arg) | ||
|
||
if (!inCache) { | ||
map.set(arg, fn(arg)) | ||
} | ||
|
||
return map.get(arg) as R | MemoizedFunction<T, R> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Value } from '../social-db/social-db.service' | ||
|
||
export type LinkIndexRules = { | ||
namespace?: boolean | ||
type?: boolean | ||
parsed: Record<string, boolean> | ||
parent?: LinkIndexRules | ||
} | ||
|
||
export type IndexedContext = { | ||
namespace?: string | ||
type?: string | ||
parsed?: Record<string, Value> | ||
parent?: IndexedContext | ||
} | ||
|
||
export type IndexObject = { | ||
appId: string | ||
mutationId: string | ||
context: IndexedContext | ||
} | ||
|
||
export type LinkedDataByAccount = { [accountId: string]: any } |
125 changes: 125 additions & 0 deletions
125
libs/engine/src/app/services/link-db/link-db.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import serializeToDeterministicJson from 'json-stringify-deterministic' | ||
|
||
import { SocialDbService } from '../social-db/social-db.service' | ||
import { TransferableContext } from '../../common/transferable-context' | ||
import { AppId } from '../application/application.entity' | ||
import { MutationId } from '../mutation/mutation.entity' | ||
import { UserLinkRepository } from '../user-link/user-link.repository' | ||
import { LinkIndexRules, IndexObject, LinkedDataByAccount } from './link-db.entity' | ||
|
||
const DefaultIndexRules: LinkIndexRules = { | ||
namespace: true, | ||
type: true, | ||
parsed: { id: true }, | ||
} | ||
|
||
const ProjectIdKey = 'dapplets.near' | ||
const SettingsKey = 'settings' | ||
const ContextLinkKey = 'ctxlink' | ||
const WildcardKey = '*' | ||
const KeyDelimiter = '/' | ||
const DataKey = 'data' | ||
|
||
export class LinkDbService { | ||
constructor(private _socialDb: SocialDbService) {} | ||
|
||
async set( | ||
mutationId: MutationId, | ||
appId: AppId, | ||
context: TransferableContext, // ToDo: replace with IContextNode? | ||
dataByAccount: LinkedDataByAccount, | ||
indexRules: LinkIndexRules = DefaultIndexRules | ||
): Promise<void> { | ||
const accounts = Object.keys(dataByAccount) | ||
|
||
// ToDo: implement multiple accounts | ||
if (accounts.length !== 1) { | ||
throw new Error('Only one account can be written at a time') | ||
} | ||
|
||
const [accountId] = accounts | ||
|
||
const indexObject = LinkDbService._buildLinkIndex(mutationId, appId, indexRules, context) | ||
const index = UserLinkRepository._hashObject(indexObject) // ToDo: the dependency is not injected | ||
|
||
const keys = [accountId, SettingsKey, ProjectIdKey, ContextLinkKey, index] | ||
|
||
const dataToStore = { | ||
[DataKey]: serializeToDeterministicJson(dataByAccount[accountId]), | ||
} | ||
|
||
await this._socialDb.set(SocialDbService.buildNestedData(keys, dataToStore)) | ||
} | ||
|
||
async get( | ||
mutationId: MutationId, | ||
appId: AppId, | ||
context: TransferableContext, | ||
accountIds: string[] | string = [WildcardKey], // from any user by default | ||
indexRules: LinkIndexRules = DefaultIndexRules // use context id as index by default | ||
): Promise<LinkedDataByAccount> { | ||
const indexObject = LinkDbService._buildLinkIndex(mutationId, appId, indexRules, context) | ||
const index = UserLinkRepository._hashObject(indexObject) // ToDo: the dependency is not injected | ||
|
||
accountIds = Array.isArray(accountIds) ? accountIds : [accountIds] | ||
|
||
const keysArr = accountIds.map((accountId) => [ | ||
accountId, | ||
SettingsKey, | ||
ProjectIdKey, | ||
ContextLinkKey, | ||
index, | ||
DataKey, | ||
]) | ||
|
||
// ToDo: too much data will be retrieved here, becuase it created by users | ||
|
||
// ToDo: batch requests | ||
const resp = await this._socialDb.get(keysArr.map((keys) => keys.join(KeyDelimiter))) | ||
|
||
const links = SocialDbService.splitObjectByDepth(resp, 6) // 6 is a number of keys in keysArr | ||
|
||
const dataByAuthor = Object.fromEntries( | ||
Object.entries(links).map(([key, json]) => { | ||
const [authorId] = key.split(KeyDelimiter) | ||
const data = json ? JSON.parse(json as string) : undefined | ||
return [authorId, data] | ||
}) | ||
) | ||
|
||
return dataByAuthor | ||
} | ||
|
||
static _buildLinkIndex( | ||
mutationId: MutationId, | ||
appId: AppId, | ||
indexRules: LinkIndexRules, | ||
context: TransferableContext | ||
): IndexObject { | ||
// MutationId is a part of the index. | ||
// It means that a data of the same application is different in different mutations | ||
|
||
return { | ||
mutationId, | ||
appId, | ||
context: LinkDbService._buildIndexedContextValues(indexRules, context), | ||
} | ||
} | ||
|
||
static _buildIndexedContextValues(indexes: any, values: any): any { | ||
const out: any = {} | ||
|
||
for (const prop in indexes) { | ||
if (!indexes[prop]) continue | ||
|
||
// ToDo: will not work with arrays | ||
if (typeof values[prop] === 'object') { | ||
out[prop] = LinkDbService._buildIndexedContextValues(indexes[prop], values[prop]) | ||
} else { | ||
out[prop] = values[prop] | ||
} | ||
} | ||
|
||
return out | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters