Skip to content

Commit

Permalink
add support for federated queries
Browse files Browse the repository at this point in the history
  • Loading branch information
tysonrm committed May 8, 2022
1 parent 7f1b155 commit 6ee834a
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 15 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ node_modules
.idea
.DS_Store
tst-rtry.js
.VSCodeCounter/2022-05-07_18-48-46/details.md
.VSCodeCounter/2022-05-07_18-48-46/diff-details.md
.VSCodeCounter/2022-05-07_18-48-46/diff.csv
.VSCodeCounter/2022-05-07_18-48-46/diff.md
.VSCodeCounter/2022-05-07_18-48-46/diff.txt
.VSCodeCounter/2022-05-07_18-48-46/results.csv
.VSCodeCounter/2022-05-07_18-48-46/results.json
.VSCodeCounter/2022-05-07_18-48-46/results.md
.VSCodeCounter/2022-05-07_18-48-46/results.txt
1 change: 1 addition & 0 deletions public/aegis.config.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"adapters": {
"desc": "adapter config",
"cacheSize": 3000,
"enableFederatedQueries": false,
"defaultDatasource": "DataSourceFile",
"datasources": {
"DataSourceMemory": {
Expand Down
8 changes: 5 additions & 3 deletions src/domain/datasource-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import dsconfig from '../adapters/datasources'
import sysconf from '../config'
import DataSource from './datasource'
import { withSharedMemory } from './shared-memory'
import compose from './util/compose'

const defaultAdapter = sysconf.hostConfig.adapters.defaultDatasource
const DefaultDataSource = adapters[defaultAdapter]
Expand Down Expand Up @@ -54,7 +55,7 @@ const DataSourceFactory = (() => {
* @property {string} adapterName specify the adapter to use
* @property {Map<string,any>|import('sharedmap').SharedMap} dsMap
* data source location and structure for private or shared memory
* @property {function(typeof DataSource):typeof DataSource} mixin
* @property {function(typeof DataSource):typeof DataSource[]} mixins
*/

/**
Expand Down Expand Up @@ -93,8 +94,9 @@ const DataSourceFactory = (() => {
const spec = ModelFactory.getModelSpec(name)
const dsMap = options.dsMap || new Map()
const DsClass = createDataSourceClass(spec, options)
const MixinClass = options.mixin ? options.mixin(DsClass) : DsClass
const newDs = new MixinClass(dsMap, this, name)
const DsMixinClass =
options.mixins.length > 0 ? compose(...options.mixins)(DsClass) : DsClass
const newDs = new DsMixinClass(dsMap, this, name)
if (!options.ephemeral) dataSources.set(name, newDs)
return newDs
}
Expand Down
2 changes: 1 addition & 1 deletion src/domain/datasource.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default class DataSource {
}

getCacheSizeBytes () {
return this.count() * roughSizeOfObject(this.dsMap.reduce(a => a))
return this.count() * roughSizeOfObject(this.findSync({ count: 1 }))
}

/**
Expand Down
34 changes: 34 additions & 0 deletions src/domain/federated-query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

import { EventBrokerFactory } from '.'
import { requireRemoteObject } from './make-relations'

export const FederationMixin = superclass =>
class extends superclass {
/**
* Deserialize
* @override
* @param {*} id
* @returns {import('.').Model}
*/
async find (id) {
try {
const result = await super.find(id)
if (!result || result.length < 1) return this.findRemote(id)
return result
} catch (error) {
console.error({ fn: 'federatedFindById', error })
}
}

async findRemote (id) {
const event = await requireRemoteObject(
null,
{ type: 'findById', modelName: this.name, id },
EventBrokerFactory.getInstance()
)
if (event?.model) return event.model
console.debug('federated findById: no model found')
return {}
}
}
24 changes: 19 additions & 5 deletions src/domain/make-relations.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export const relationType = {
containsMany: async (model, ds, rel) =>
await Promise.all(
model[rel.arrayKey].map(arrayItem => ds.find(arrayItem[rel.foreignKey]))
)
),
findById: async (model, ds, rel) => ds.find(id)
}

const referentialIntegrity = {
Expand Down Expand Up @@ -134,13 +135,26 @@ export function requireRemoteObject (model, relation, broker, ...args) {

console.debug({ fn: requireRemoteObject.name })

if (!model && relation.type !== 'findById') {
console.error({
fn: requireRemoteObject.name,
error: 'model param missing'
})
return
}

const name = (model ? model.getName() : relation.modelName).toUpperCase()
const id = model ? model.getId() : relation.id
const eventSource = name
const eventTarget = model ? relation.modelName.toUpperCase() : null

const requestData = {
eventName: request,
modelName: model.getName().toUpperCase(),
modelName: name,
eventType: externalCacheRequest.name,
eventSource: model.getName().toUpperCase(),
eventTarget: relation.modelName.toUpperCase(),
modelId: model.getId(),
eventSource,
eventTarget,
modelId: id,
relation,
model,
args
Expand Down
6 changes: 4 additions & 2 deletions src/domain/shared-memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ export function withSharedMemory (
return createDataSource.call(factory, name, {
...options,
dsMap: sharedMap,
mixin: DsClass =>
class DataSourceSharedMemory extends SharedMemoryMixin(DsClass) {}
mixins: [
DsClass =>
class DataSourceSharedMemory extends SharedMemoryMixin(DsClass) {}
].concat(options.mixins)
})

return createDataSource.call(factory, name, options)
Expand Down
21 changes: 17 additions & 4 deletions src/domain/use-cases/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ import makeHotReload from './hot-reload'
import brokerEvents from './broker-events'

import { isMainThread } from 'worker_threads'
import { FederationMixin } from '../federated-query'

const dsOpts = {
mixins: [
DsClass => class DataSourceFederated extends FederationMixin(DsClass) {}
]
}

export function registerEvents () {
// main thread handles event dispatch
Expand Down Expand Up @@ -44,7 +51,7 @@ function findLocalRelatedModels (modelName) {
function findLocalRelatedDatasources (modelName) {
return findLocalRelatedModels(modelName).map(modelName => ({
modelName,
dsMap: DataSourceFactory.getSharedDataSource(modelName).dsMap
dsMap: DataSourceFactory.getSharedDataSource(modelName, dsOpts).dsMap
}))
}

Expand All @@ -64,20 +71,26 @@ function buildOptions (model) {
return {
...options,
// main thread does not write to persistent store
repository: DataSourceFactory.getSharedDataSource(model.modelName),
repository: DataSourceFactory.getSharedDataSource(
model.modelName,
dsOpts
),

// only main thread knows about thread pools (no nesting)
threadpool: ThreadPoolFactory.getThreadPool(model.modelName, {
preload: false,
sharedMap: DataSourceFactory.getSharedDataSource(model.modelName).dsMap,
sharedMap: DataSourceFactory.getSharedDataSource(
model.modelName,
dsOpts
).dsMap,
dsRelated: findLocalRelatedDatasources(model.modelName)
})
}
} else {
return {
...options,
// only worker threads can write to persistent storage
repository: DataSourceFactory.getSharedDataSource(model.modelName)
repository: DataSourceFactory.getSharedDataSource(model.modelName, dsOpts)
}
}
}
Expand Down

0 comments on commit 6ee834a

Please sign in to comment.