Skip to content

Commit

Permalink
resolve up/down precision improved
Browse files Browse the repository at this point in the history
  • Loading branch information
arietrouw committed Aug 1, 2023
1 parent fbe162f commit 060f3be
Show file tree
Hide file tree
Showing 38 changed files with 426 additions and 56 deletions.
12 changes: 6 additions & 6 deletions packages/manifest/src/spec/Manifest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ describe('Manifest', () => {
expect(node).toBeDefined()
const discover = await node.discover()
const discoveredAddresses = discover.filter((item) => item.schema === AddressSchema)
expect(discoveredAddresses.length).toBeGreaterThan(4)
expect(await node.resolve()).toBeArrayOfSize(15)
expect(discoveredAddresses.length).toBe(4)
expect((await node.resolve()).length).toBeGreaterThan(10)
const roundTrip = await node.manifest()
expect(roundTrip.modules?.private).toBeArrayOfSize(1)
expect(roundTrip.modules?.public).toBeArrayOfSize(14)
expect(roundTrip.modules?.public?.length).toBeGreaterThan(10)
})
})
describe('Create Node from Manifest [Lazy]', () => {
Expand All @@ -32,11 +32,11 @@ describe('Manifest', () => {
expect(node).toBeDefined()
const discover = await node.discover()
const discoveredAddresses = discover.filter((item) => item.schema === AddressSchema)
expect(discoveredAddresses.length).toBeGreaterThan(4)
expect(await node.resolve()).toBeArrayOfSize(15)
expect(discoveredAddresses.length).toBe(4)
expect((await node.resolve()).length).toBeGreaterThan(10)
const roundTrip = await node.manifest()
expect(roundTrip.modules?.private).toBeArrayOfSize(1)
expect(roundTrip.modules?.public).toBeArrayOfSize(14)
expect(roundTrip.modules?.public?.length).toBeGreaterThan(10)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
AddressModuleFilter,
Module,
ModuleFilter,
ModuleFilterOptions,
ModuleInstance,
ModuleResolver,
NameModuleFilter,
Expand Down Expand Up @@ -93,22 +94,37 @@ export class BridgeModuleResolver extends CompositeModuleResolver implements Mod
throw new Error('Method not implemented.')
}

override async resolve(filter?: ModuleFilter): Promise<ModuleInstance[]>
override async resolve(nameOrAddress: string): Promise<ModuleInstance | undefined>
override async resolve(nameOrAddressOrFilter?: ModuleFilter | string): Promise<ModuleInstance | ModuleInstance[] | undefined> {
override async resolve<T extends ModuleInstance = ModuleInstance>(
filter?: ModuleFilter<T>,
options?: ModuleFilterOptions<T>,
): Promise<ModuleInstance[]>
override async resolve<T extends ModuleInstance = ModuleInstance>(
nameOrAddress: string,
options?: ModuleFilterOptions<T>,
): Promise<ModuleInstance | undefined>
override async resolve<T extends ModuleInstance = ModuleInstance>(
nameOrAddressOrFilter?: ModuleFilter<T> | string,
options?: ModuleFilterOptions<T>,
): Promise<ModuleInstance | ModuleInstance[] | undefined> {
const mutatedOptions = { ...options, maxDepth: (options?.maxDepth ?? BridgeModuleResolver.defaultMaxDepth) - 1 }
await this.prime()
await this.resolveRemoteModules()
if (typeof nameOrAddressOrFilter === 'string') {
const result: ModuleInstance | undefined =
(await this.resolveByAddress(nameOrAddressOrFilter)) ?? (await this.resolveByName(nameOrAddressOrFilter))
if (mutatedOptions.maxDepth < 0) {
return undefined
}
const result: T | undefined = (await this.resolveByAddress<T>(nameOrAddressOrFilter)) ?? (await this.resolveByName<T>(nameOrAddressOrFilter))
return result
} else {
const result: ModuleInstance[] = await this.resolveRemoteModules(nameOrAddressOrFilter)
if (mutatedOptions.maxDepth < 0) {
return []
}
const result: T[] = await this.resolveRemoteModules<T>(nameOrAddressOrFilter)
return result
}
}

private async resolveByAddress(targetAddress: string): Promise<ModuleInstance | undefined> {
private async resolveByAddress<T extends ModuleInstance = ModuleInstance>(targetAddress: string): Promise<T | undefined> {
const remoteAddresses = await this.getRemoteAddresses()

//check if it is even there
Expand All @@ -118,7 +134,7 @@ export class BridgeModuleResolver extends CompositeModuleResolver implements Mod
}

const cached = this.resolvedModules[targetAddress]
if (cached) return await cached
if (cached) return (await cached) as T

this.resolvedModules[targetAddress] =
this.resolvedModules[targetAddress] ??
Expand Down Expand Up @@ -157,52 +173,52 @@ export class BridgeModuleResolver extends CompositeModuleResolver implements Mod
}
})(targetAddress)

return await this.resolvedModules[targetAddress]
return (await this.resolvedModules[targetAddress]) as T
}

private async resolveByName(name: string): Promise<ModuleInstance | undefined> {
private async resolveByName<T extends ModuleInstance = ModuleInstance>(name: string): Promise<T | undefined> {
const modules = await this.currentResolvedModules()
return Object.values(modules)
.filter((module) => module.config.name === name)
.pop()
.pop() as T
}

private async resolveByQuery(queries: string[]): Promise<ModuleInstance[]> {
private async resolveByQuery<T extends ModuleInstance = ModuleInstance>(queries: string[]): Promise<T[]> {
return Object.values(await this.currentResolvedModules()).filter((module) => {
//filter out the requested queries
const found = module.queries.filter((query) => queries.find((q) => q === query))

//did we find all the requested queries?
return queries.length === found.length
})
}) as T[]
}

private async resolveRemoteModules(filter?: ModuleFilter): Promise<ModuleInstance[]> {
private async resolveRemoteModules<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter): Promise<T[]> {
if ((filter as AddressModuleFilter)?.address) {
return await this.resolveRemoteModulesByAddress(filter as AddressModuleFilter)
return await this.resolveRemoteModulesByAddress<T>(filter as AddressModuleFilter)
}

if ((filter as NameModuleFilter)?.name) {
return await this.resolveRemoteModulesByName(filter as NameModuleFilter)
return await this.resolveRemoteModulesByName<T>(filter as NameModuleFilter)
}

if ((filter as QueryModuleFilter)?.query) {
return await this.resolveRemoteModulesByQuery(filter as QueryModuleFilter)
return await this.resolveRemoteModulesByQuery<T>(filter as QueryModuleFilter)
}

//get all of them
return await this.resolveRemoteModulesByAddress({ address: await this.getRemoteAddresses() })
return await this.resolveRemoteModulesByAddress<T>({ address: await this.getRemoteAddresses() })
}

private async resolveRemoteModulesByAddress(filter: AddressModuleFilter): Promise<ModuleInstance[]> {
return compact(await Promise.all(filter.address.map((address) => this.resolveByAddress(address))))
private async resolveRemoteModulesByAddress<T extends ModuleInstance = ModuleInstance>(filter: AddressModuleFilter): Promise<T[]> {
return compact(await Promise.all(filter.address.map((address) => this.resolveByAddress<T>(address))))
}

private async resolveRemoteModulesByName(filter: NameModuleFilter): Promise<ModuleInstance[]> {
return compact(await Promise.all(filter.name.map(async (name) => await this.resolveByName(name))))
private async resolveRemoteModulesByName<T extends ModuleInstance = ModuleInstance>(filter: NameModuleFilter): Promise<T[]> {
return compact(await Promise.all(filter.name.map(async (name) => await this.resolveByName<T>(name))))
}

private async resolveRemoteModulesByQuery(filter: QueryModuleFilter): Promise<ModuleInstance[]> {
return compact((await Promise.all(filter.query.map(async (query) => await this.resolveByQuery(query)))).flat())
private async resolveRemoteModulesByQuery<T extends ModuleInstance = ModuleInstance>(filter: QueryModuleFilter): Promise<T[]> {
return compact((await Promise.all(filter.query.map(async (query) => await this.resolveByQuery<T>(query)))).flat())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,15 @@ export abstract class AbstractModule<
switch (typeof nameOrAddressOrFilter) {
case 'string': {
return (
(down ? await (this.downResolver as CompositeModuleResolver).resolve(nameOrAddressOrFilter) : undefined) ??
(up ? await (this.upResolver as ModuleResolver).resolve(nameOrAddressOrFilter) : undefined)
(down ? await (this.downResolver as CompositeModuleResolver).resolve(nameOrAddressOrFilter, options) : undefined) ??
(up ? await (this.upResolver as ModuleResolver).resolve(nameOrAddressOrFilter, options) : undefined)
)
}
default: {
const filter: ModuleFilter | undefined = nameOrAddressOrFilter
return [
...(down ? await (this.downResolver as CompositeModuleResolver).resolve(filter) : []),
...(up ? await (this.upResolver as ModuleResolver).resolve(filter) : []),
...(down ? await (this.downResolver as CompositeModuleResolver).resolve(filter, options) : []),
...(up ? await (this.upResolver as ModuleResolver).resolve(filter, options) : []),
].filter(duplicateModules)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export abstract class AbstractModuleInstance<
// Clone params to prevent mutation of the incoming object
const mutatedParams = { ...params } as TParams
super(privateConstructorKey, mutatedParams, account)
this.upResolver.add(this)
this.downResolver.add(this)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { exists } from '@xylabs/exists'
import { Base, BaseParams } from '@xyo-network/core'
import { duplicateModules, ModuleFilter, ModuleInstance, ModuleRepository, ModuleResolver } from '@xyo-network/module-model'
import { duplicateModules, ModuleFilter, ModuleFilterOptions, ModuleInstance, ModuleRepository, ModuleResolver } from '@xyo-network/module-model'

import { SimpleModuleResolver } from './SimpleModuleResolver'

export class CompositeModuleResolver extends Base implements ModuleRepository, ModuleResolver {
static defaultMaxDepth = 4
protected resolvers: ModuleResolver[] = []
private localResolver: SimpleModuleResolver

Expand Down Expand Up @@ -49,22 +50,35 @@ export class CompositeModuleResolver extends Base implements ModuleRepository, M
return this
}

async resolve(filter?: ModuleFilter): Promise<ModuleInstance[]>
async resolve(nameOrAddress: string): Promise<ModuleInstance | undefined>
async resolve(nameOrAddressOrFilter?: ModuleFilter | string): Promise<ModuleInstance | ModuleInstance[] | undefined> {
async resolve<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter<T>, options?: ModuleFilterOptions<T>): Promise<ModuleInstance[]>
async resolve<T extends ModuleInstance = ModuleInstance>(
nameOrAddress: string,
options?: ModuleFilterOptions<T>,
): Promise<ModuleInstance | undefined>
async resolve<T extends ModuleInstance = ModuleInstance>(
nameOrAddressOrFilter?: ModuleFilter<T> | string,
options?: ModuleFilterOptions<T>,
): Promise<ModuleInstance | ModuleInstance[] | undefined> {
const mutatedOptions = { ...options, maxDepth: (options?.maxDepth ?? CompositeModuleResolver.defaultMaxDepth) - 1 }
if (typeof nameOrAddressOrFilter === 'string') {
if (mutatedOptions.maxDepth < 0) {
return undefined
}
const results = await Promise.all(
this.resolvers.map(async (resolver) => {
const result: ModuleInstance | undefined = await resolver.resolve(nameOrAddressOrFilter)
const result: ModuleInstance | undefined = await resolver.resolve(nameOrAddressOrFilter, mutatedOptions)
return result
}),
)
const result: ModuleInstance | undefined = results.filter(exists).filter(duplicateModules).pop()
return result
} else {
if (mutatedOptions.maxDepth < 0) {
return []
}
const result = await Promise.all(
this.resolvers.map(async (resolver) => {
const result: ModuleInstance[] = await resolver.resolve(nameOrAddressOrFilter)
const result: ModuleInstance[] = await resolver.resolve(nameOrAddressOrFilter, mutatedOptions)
return result
}),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class IsInstanceFactory<T extends ModuleInstance = ModuleInstance> extend
export interface ModuleFilterOptions<T extends ModuleInstance = ModuleInstance> {
direction?: 'up' | 'down' | 'all'
identity?: InstanceTypeCheck<T>
maxDepth?: number
visibility?: 'public' | 'private' | 'all'
}

Expand Down
2 changes: 1 addition & 1 deletion packages/modules/packages/node/packages/model/src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export type NodeInstance<
> = NodeModule<TParams, TEventData> &
NodeQueryFunctions &
ModuleInstance & {
register: (module: ModuleInstance) => void
register: (module: ModuleInstance) => Promisable<void>
registeredModules(): Promisable<ModuleInstance[]>
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,15 @@ describe('MemoryNode', () => {
}
}
}

expect((await node.resolve(undefined, { direction: 'up' })).length).toBe(1)
expect((await node.resolve(undefined, { direction: 'down' })).length).toBe(3)
expect((await node.resolve(undefined, { direction: 'down', maxDepth: 1 })).length).toBe(1)
expect((await node.resolve(undefined, { direction: 'all' })).length).toBe(3)

expect((await archivist.resolve(undefined, { direction: 'up' })).length).toBe(3)
expect((await archivist.resolve(undefined, { direction: 'up', maxDepth: 1 })).length).toBe(1)
expect((await archivist.resolve(undefined, { direction: 'down' })).length).toBe(1)
expect((await archivist.resolve(undefined, { direction: 'all' })).length).toBe(3)
})
})
2 changes: 1 addition & 1 deletion packages/modules/packages/node/src/AbstractNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export abstract class AbstractNode<TParams extends NodeModuleParams = NodeModule
}

async attachedModules(): Promise<Module[]> {
return (await (this.resolve() ?? [])).filter((module) => module.address !== this.address)
return (await (this.resolve(undefined, { direction: 'down', maxDepth: 2 }) ?? [])).filter((module) => module.address !== this.address)
}

override async manifest(ignoreAddresses?: string[]): Promise<NodeManifestPayload> {
Expand Down
1 change: 1 addition & 0 deletions packages/modules/packages/sentinel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@xyo-network/payload-model": "workspace:~",
"@xyo-network/payload-wrapper": "workspace:~",
"@xyo-network/promise": "workspace:~",
"@xyo-network/sentinel-model": "workspace:~",
"@xyo-network/witness": "workspace:~",
"lodash": "^4.17.21"
},
Expand Down
21 changes: 21 additions & 0 deletions packages/modules/packages/sentinel/packages/model/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.*
.env
.eslintcache
.example.env
tsconfig*
jest.config.js
rollup.config.ts
yarn.lock
**/*.spec.ts
**/*.snap

.github
docs
.pnp.*
.vscode
.yarn/*
coverage
cspell.json
node_modules
swagger.json
packages
Loading

0 comments on commit 060f3be

Please sign in to comment.