Skip to content

Commit

Permalink
Feature/hot read models (#1910)
Browse files Browse the repository at this point in the history
  • Loading branch information
IhostVlad authored Jun 24, 2021
1 parent 23fa915 commit cff42b2
Show file tree
Hide file tree
Showing 13 changed files with 446 additions and 317 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import type {
CommonAdapterPool,
CommonAdapterOptions,
AdapterImplementation,
BaseAdapterImports,
BaseAdapterPool,
AdapterOperations,
AdapterApi,
ObjectKeys,
StoreApi,
} from './types'

const createAdapter = <
AdapterPool extends CommonAdapterPool,
AdapterOptions extends CommonAdapterOptions
>(
imports: BaseAdapterImports,
implementation: AdapterImplementation<AdapterPool, AdapterOptions>,
options: AdapterOptions
): AdapterApi<AdapterPool> => {
const {
splitNestedPath,
checkEventsContinuity,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
} = imports

const {
connect,
disconnect,
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
...restApi
} = implementation

if (Object.keys(restApi).length > 0) {
throw new Error(
`Read model adapter implementation should not provide extra methods: ${JSON.stringify(
Object.keys(restApi)
)}`
)
}

const storeApi: StoreApi<AdapterPool> = {
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
}

const adapterOperations: AdapterOperations<AdapterPool> = {
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
}

for (const key of Object.keys(storeApi) as ObjectKeys<
StoreApi<AdapterPool>
>) {
if (typeof storeApi[key] !== 'function') {
throw new Error(`Store API method ${key} should be a function`)
}
}

for (const key of Object.keys(adapterOperations) as ObjectKeys<
AdapterOperations<AdapterPool>
>) {
if (typeof adapterOperations[key] !== 'function') {
throw new Error(`Adapter operation method ${key} should be a function`)
}
}

const { performanceTracer, monitoring, ...adapterOptions } = options

const pool: BaseAdapterPool<AdapterPool> = {
commonAdapterPool: {
performanceTracer,
checkEventsContinuity,
splitNestedPath,
monitoring,
},
adapterPoolMap: new Map(),
withPerformanceTracer,
performanceTracer,
monitoring,
}

const adapter: AdapterApi<AdapterPool> = {
connect: wrapConnect(pool, connect, storeApi, adapterOptions),
disconnect: wrapDisconnect(pool, disconnect),
dispose: wrapDispose(pool, disconnect),
subscribe: wrapOperation(pool, 'subscribe', subscribe),
unsubscribe: wrapOperation(pool, 'unsubscribe', unsubscribe),
resubscribe: wrapOperation(pool, 'resubscribe', resubscribe),
resume: wrapOperation(pool, 'resume', resume),
pause: wrapOperation(pool, 'pause', pause),
reset: wrapOperation(pool, 'reset', reset),
status: wrapOperation(pool, 'status', status),
build: wrapOperation(pool, 'build', build),
}

return Object.freeze(adapter)
}

export default createAdapter
Original file line number Diff line number Diff line change
@@ -1,124 +1,31 @@
import type {
CommonAdapterPool,
CommonAdapterOptions,
AdapterImplementation,
BaseAdapterImports,
BaseAdapterPool,
AdapterOperations,
AdapterApi,
ObjectKeys,
StoreApi,
} from './types'

const createAdapter = <
AdapterPool extends CommonAdapterPool,
AdapterOptions extends CommonAdapterOptions
>(
imports: BaseAdapterImports,
implementation: AdapterImplementation<AdapterPool, AdapterOptions>,
options: AdapterOptions
): AdapterApi<AdapterPool> => {
const {
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
} = imports
const splitNestedPath = makeSplitNestedPath(imports)

const {
connect,
disconnect,
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
...restApi
} = implementation

if (Object.keys(restApi).length > 0) {
throw new Error(
`Read model adapter implementation should not provide extra methods: ${JSON.stringify(
Object.keys(restApi)
)}`
)
}

const storeApi: StoreApi<AdapterPool> = {
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
}

const adapterOperations: AdapterOperations<AdapterPool> = {
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
}

for (const key of Object.keys(storeApi) as ObjectKeys<
StoreApi<AdapterPool>
>) {
if (typeof storeApi[key] !== 'function') {
throw new Error(`Store API method ${key} should be a function`)
}
}

for (const key of Object.keys(adapterOperations) as ObjectKeys<
AdapterOperations<AdapterPool>
>) {
if (typeof adapterOperations[key] !== 'function') {
throw new Error(`Adapter operation method ${key} should be a function`)
}
}

const { performanceTracer, monitoring, ...adapterOptions } = options

const pool: BaseAdapterPool<AdapterPool> = {
commonAdapterPool: { performanceTracer, splitNestedPath, monitoring },
adapterPoolMap: new Map(),
withPerformanceTracer,
performanceTracer,
monitoring,
}

const adapter: AdapterApi<AdapterPool> = {
connect: wrapConnect(pool, connect, storeApi, adapterOptions),
disconnect: wrapDisconnect(pool, disconnect),
dispose: wrapDispose(pool, disconnect),
subscribe: wrapOperation(pool, 'subscribe', subscribe),
unsubscribe: wrapOperation(pool, 'unsubscribe', unsubscribe),
resubscribe: wrapOperation(pool, 'resubscribe', resubscribe),
resume: wrapOperation(pool, 'resume', resume),
pause: wrapOperation(pool, 'pause', pause),
reset: wrapOperation(pool, 'reset', reset),
status: wrapOperation(pool, 'status', status),
build: wrapOperation(pool, 'build', build),
}

return Object.freeze(adapter)
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'
import { checkEventsContinuity } from '@resolve-js/eventstore-base'

import _createAdapter from './create-adapter-factory'
import makeSplitNestedPath from './make-split-nested-path'
import withPerformanceTracer from './with-performance-tracer'
import wrapConnect from './wrap-connect'
import wrapDisconnect from './wrap-disconnect'
import wrapDispose from './wrap-dispose'
import wrapOperation from './wrap-operation'
import { CreateAdapterMethod } from './types'

const baseAdapterImports = {
splitNestedPath: makeSplitNestedPath(PathToolkit),
checkEventsContinuity,
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
}

const createAdapter = _createAdapter.bind(
null,
baseAdapterImports
) as CreateAdapterMethod

export default createAdapter
Original file line number Diff line number Diff line change
@@ -1,34 +1,3 @@
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'

import _createAdapter from './create-adapter'
import makeSplitNestedPath from './make-split-nested-path'
import withPerformanceTracer from './with-performance-tracer'
import wrapConnect from './wrap-connect'
import wrapDisconnect from './wrap-disconnect'
import wrapDispose from './wrap-dispose'
import wrapOperation from './wrap-operation'
import { CreateAdapterMethod } from './types'
export { default as default } from './create-adapter'
export { default as splitNestedPath } from './split-nested-path'
export * from './types'

const baseAdapterImports = {
PathToolkit,
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
}

const createAdapter = _createAdapter.bind(
null,
baseAdapterImports
) as CreateAdapterMethod

const splitNestedPath = makeSplitNestedPath(baseAdapterImports)

export default createAdapter

export { splitNestedPath }
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MakeSplitNestedPathMethod, SplitNestedPathMethod } from './types'

const makeSplitNestedPath: MakeSplitNestedPathMethod = (imports) => {
const pathToolkit = new imports.PathToolkit()
const makeSplitNestedPath: MakeSplitNestedPathMethod = (PathToolkit) => {
const pathToolkit = new PathToolkit()
pathToolkit.setOptions({
cache: false,
force: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'
import makeSplitNestedPath from './make-split-nested-path'

const splitNestedPath = makeSplitNestedPath(PathToolkit)

export default splitNestedPath
Loading

0 comments on commit cff42b2

Please sign in to comment.