Skip to content

Commit

Permalink
feat: refactor the observer structure
Browse files Browse the repository at this point in the history
  • Loading branch information
ChoGathK committed Oct 12, 2022
1 parent d9c14c1 commit de7cd34
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 44 deletions.
81 changes: 64 additions & 17 deletions src/common/interface/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { ConfigHandlerOptions } from './options';

interface Observer {
contrast: (...args: any[]) => void;
subscribe: (...args: any[]) => void | Promise<void>;
notify: (...args: any[]) => void;
polling: (...args: any[]) => void | Promise<void>;
unPolling: (...args: any[]) => void | Promise<void>;
unSubscribe: (...args: any[]) => void;
}

export interface IConfig<T = any> {
/**
* Deep search the configuration with property key.
Expand Down Expand Up @@ -48,6 +57,17 @@ export interface IConfigSubscriber {
update: (key: string, value: any) => void | Promise<void>
}

export interface IConfigClientSubscriber {
/**
* Updating Configuration.
*
* @param value any The configuration value.
*
* @publicApi
*/
update: (value: any) => void | Promise<void>
}

export interface IConfigLoader {
/**
* Load configuration.
Expand All @@ -72,7 +92,7 @@ export interface IConfigPoller {
close: () => void | Promise<void>;
}

export interface IConfigObserver {
export interface IConfigObserver extends Observer {
/**
* Contrasting configuration.
*
Expand All @@ -81,16 +101,16 @@ export interface IConfigObserver {
*
* @publicApi
*/
contrast?: (key: string, value: any) => void;
contrast: (key: string, value: any) => void;
/**
* Register the subscriber inside client by the key of configuration.
*
* @param key string The key of configuration.
* @param value any The configuration value.
* @param subscriber IConfigSubscriber The configuration subscriber..
*
* @publicApi
*/
subscribe?: (key: string, subscriber: IConfigSubscriber) => void;
subscribe: (key: string, subscriber: IConfigSubscriber) => void | Promise<void>;
/**
* Notify subscribers of configuration updates.
*
Expand All @@ -99,30 +119,30 @@ export interface IConfigObserver {
*
* @publicApi
*/
notify?: (key: string, value: any) => void;
notify: (key: string, value: any) => void;
/**
* Open the polling.
*
* @publicApi
*/
polling?: () => void | Promise<void>;
polling: () => void | Promise<void>;
/**
* Close the polling.
*
* @publicApi
*/
unPolling?: () => void | Promise<void>;
unPolling: () => void | Promise<void>;
/**
* Remove the subscriber from client by the key of configuration..
*
* @param key string The key of configuration.
*
* @publicApi
*/
unSubscribe?: (key: string) => void;
unSubscribe: (key: string) => void;
}

export interface IConfigClient extends IConfigObserver {
export interface IConfigClient extends Observer {
/**
* Load configuration.
*
Expand All @@ -132,20 +152,47 @@ export interface IConfigClient extends IConfigObserver {
*/
load: <T = any>(loader: IConfigLoader) => T | Promise<T>;
/**
* Register the subscriber inside client.
* Contrasting configuration.
*
* @param key string The key of configuration.
* @param value any The configuration value.
*
* @publicApi
*/
subscribeAll?: (subscriber: IConfigSubscriber) => void;
contrast: (value: any) => void;
/**
* Remove the subscriber from client.
*
* @publicApi
*/
unSubscribeAll?: () => void;
* Register the subscriber inside client by the key of configuration.
*
* @param subscriber IConfigClientSubscriber The configuration client subscriber.
*
* @publicApi
*/
subscribe: (subscriber: IConfigClientSubscriber) => void | Promise<void>;
/**
* Notify subscribers of configuration updates.
*
* @param value any The configuration value.
*
* @publicApi
*/
notify: (value: any) => void;
/**
* Open the polling.
*
* @publicApi
*/
polling: () => void | Promise<void>;
/**
* Close the polling.
*
* @publicApi
*/
unPolling: () => void | Promise<void>;
/**
* Remove the subscriber from client by the key of configuration..
*
* @publicApi
*/
unSubscribe: () => void;
}

export interface IConfigHandler<T = any> {
Expand Down
2 changes: 1 addition & 1 deletion src/common/interface/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface ConfigClientOptions {
client: IConfigClient;
loader: IConfigLoader;
enablePolling?: boolean;
enableSubscribeAll?: boolean;
enableSubscribe?: boolean;
}

export interface ConfigHandlerOptions<T = any> {
Expand Down
2 changes: 1 addition & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import {
export class ArkModule {
static forRoot(options: ArkOptions): DynamicModule {
const manager = new ArkManager().create(options);
const { enableDynamicDataSource, global, imports } = options;

const providers: any[] = [ConfigProvider, manager];
const { enableDynamicDataSource, global, imports } = options;

if (enableDynamicDataSource) {
providers.push(AsyncDynamicDataSourceProvider);
Expand Down
4 changes: 2 additions & 2 deletions src/provider/config-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { This } from '@vodyani/class-decorator';
import { AsyncInjectable, AsyncProvider, AsyncProviderFactory } from '@vodyani/core';

import { ArkOptions } from '../common';
import { ConfigSubscriber } from '../struct';
import { ConfigClientSubscriber } from '../struct';
import { ConfigArgumentHandler, ConfigClientHandler, DynamicDataSourceConfigObserverHandler } from '../struct/config-handler';

import { ConfigProvider } from './config';
Expand Down Expand Up @@ -40,7 +40,7 @@ export class ArkManager extends AsyncProvider implements AsyncProviderFactory {
const handler = new ConfigArgumentHandler(config);

if (this.options.clients) {
const subscriber = new ConfigSubscriber(config);
const subscriber = new ConfigClientSubscriber(config);
const clientHandler = new ConfigClientHandler(subscriber);

handlers.push(clientHandler);
Expand Down
2 changes: 2 additions & 0 deletions src/provider/dynamic-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export class DynamicDataSourceConfigObserver<T = any> implements IConfigObserver

if (afterHash !== beforeHash) {
this.notify(key, value);
this.hash.set(key, afterHash);
}
}

Expand Down Expand Up @@ -174,6 +175,7 @@ export class DynamicDataSourceConfigObserver<T = any> implements IConfigObserver
private circularContrast() {
this.keys.forEach((key) => {
const value = this.config.get(key);

this.contrast(key, value);
});
}
Expand Down
40 changes: 38 additions & 2 deletions src/struct/config-client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import { IConfigClient, IConfigLoader } from '../common';
import { IConfigClient, IConfigLoader, IConfigClientSubscriber, toHash } from '../common';

export abstract class ConfigClient implements IConfigClient {
private subscriber: IConfigClientSubscriber;

private hash: string;

public contrast(value: any) {
const afterHash = toHash(value);
const beforeHash = this.hash;

if (afterHash !== beforeHash) {
this.notify(value);
this.hash = afterHash;
}
}

export class LocalConfigClient implements IConfigClient {
public load<T = any>(loader: IConfigLoader) {
return loader.execute<T>();
}

public subscribe(subscriber: IConfigClientSubscriber) {
this.subscriber = subscriber;
}

public notify(value: any) {
this.subscriber.update(value);
}

public polling() {
// do somethings ...
}

public unPolling() {
// do somethings ...
}

public unSubscribe() {
this.subscriber = null;
}
}

export class LocalConfigClient extends ConfigClient {}
20 changes: 10 additions & 10 deletions src/struct/config-handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ConfigHandlerOptions, IConfig, IConfigHandler, IConfigObserver, IConfigSubscriber } from '../common';
import { ConfigHandlerOptions, IConfig, IConfigClientSubscriber, IConfigHandler, IConfigObserver } from '../common';

abstract class AbstractConfigHandler<T = any> implements IConfigHandler<T> {
abstract class ConfigHandler<T = any> implements IConfigHandler<T> {
protected next: IConfigHandler;

public setNext(handler: IConfigHandler) {
Expand All @@ -16,7 +16,7 @@ abstract class AbstractConfigHandler<T = any> implements IConfigHandler<T> {
}
}

export class ConfigArgumentHandler<T = any> extends AbstractConfigHandler<T> {
export class ConfigArgumentHandler<T = any> extends ConfigHandler<T> {
constructor(
private readonly config: IConfig<T>,
) {
Expand All @@ -30,31 +30,31 @@ export class ConfigArgumentHandler<T = any> extends AbstractConfigHandler<T> {
}
}

export class ConfigClientHandler<T = any> extends AbstractConfigHandler<T> {
export class ConfigClientHandler<T = any> extends ConfigHandler<T> {
constructor(
private readonly subscriber: IConfigSubscriber,
private readonly subscriber: IConfigClientSubscriber,
) {
super();
}

public async execute(options: ConfigHandlerOptions<T>) {
for (const { client, loader, enablePolling, enableSubscribeAll } of options.clients) {
for (const { client, loader, enablePolling, enableSubscribe } of options.clients) {
await client.load(loader);

if (enablePolling && client.polling) {
if (enablePolling) {
await client.polling();
}

if (enableSubscribeAll && client.subscribeAll) {
client.subscribeAll(this.subscriber);
if (enableSubscribe) {
await client.subscribe(this.subscriber);
}
}

await super.execute(options);
}
}

export class DynamicDataSourceConfigObserverHandler<T = any> extends AbstractConfigHandler<T> {
export class DynamicDataSourceConfigObserverHandler<T = any> extends ConfigHandler<T> {
constructor(
private readonly observer: IConfigObserver,
) {
Expand Down
14 changes: 7 additions & 7 deletions src/struct/config-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,34 @@ export class JSONConfigLoader implements IConfigLoader {
) {}

public execute() {
const defaultResult = this.readJSON(this.defaultEnv);
const currentResult = this.readJSON(this.currentEnv);
const defaultResult = this.readJSONFile(this.defaultEnv);
const currentResult = this.readJSONFile(this.currentEnv);
const result = toDeepMatch(defaultResult, currentResult);
return result;
}

private readJSON(env: string) {
private readJSONFile(env: string) {
const str = readFileSync(`${this.path}/${env}.json`, { encoding: 'utf8' });
const result = JSON.parse(str);
return result;
}
}

export class YAMLConfigLoader implements IConfigLoader {
export class YamlConfigLoader implements IConfigLoader {
constructor(
private readonly path: string,
private readonly defaultEnv: string,
private readonly currentEnv: string,
) {}

public execute() {
const defaultResult = this.readJSON(this.defaultEnv);
const currentResult = this.readJSON(this.currentEnv);
const defaultResult = this.readYamlFile(this.defaultEnv);
const currentResult = this.readYamlFile(this.currentEnv);
const result = toDeepMatch(defaultResult, currentResult);
return result;
}

private readJSON(env: string) {
private readYamlFile(env: string) {
const str = readFileSync(`${this.path}/${env}.yml`, { encoding: 'utf8' });
const result = Yaml.load(str) as any;
return result;
Expand Down
8 changes: 4 additions & 4 deletions src/struct/config-subscriber.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { IConfig, IConfigSubscriber } from '../common';
import { IConfig, IConfigClientSubscriber } from '../common';

export class ConfigSubscriber implements IConfigSubscriber {
export class ConfigClientSubscriber implements IConfigClientSubscriber {
constructor(
private readonly config: IConfig,
) {}

public update(key: string, value: any) {
this.config.set(key, value);
public update(value: any) {
this.config.merge(value);
}
}

0 comments on commit de7cd34

Please sign in to comment.