All files / src/utils DomainAutoRefreshUtils.ts

86.36% Statements 38/44
71.42% Branches 10/14
80% Functions 12/15
88.09% Lines 37/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123    67x                                                                 9x     9x 9x 9x 9x     9x 11x 2x 2x   1x       9x     9x 6x           6x 6x                   9x 1x           1x 1x                   9x 8x 2x 2x   6x 6x   8x 2x 2x     2x 2x 1x 1x                 67x 2x 1x   2x  
import { getNetworkService, NetworkService } from "@utils/WebsocketUtils";
 
const DOMAIN_DATA_CHANGE_TOPIC = 'domain_data_change';
 
interface DomainDataChangeSubscriberRequestPayload {
  domainName: string;
  action: 'subscribe' | 'unsubscribe';
}
 
interface DomainDataChangeSubscriberResponsePayload {
  status: 'success' | 'failed';
}
 
export type UnsubscribeCallback = () => void;
 
export enum DomainChangeEventTypeEnum {
  CREATE = 'CREATE',
  UPDATE = 'UPDATE',
  DELETE = 'DELETE',
}
 
export interface DomainDataChangeEvent {
  ids: number[];
  eventType: DomainChangeEventTypeEnum;
}
 
interface DomainDataChangeRawEvent extends DomainDataChangeEvent {
  domainName: string;
}
 
export type DomainDataChangeEventListener = (event: DomainDataChangeEvent) => void;
 
export class DomainAutoRefreshService {
 
  private readonly networkService: NetworkService;
  private readonly listenerRecord: Record<string, Array<DomainDataChangeEventListener>> = {};
 
  constructor(networkService: NetworkService) {
    this.networkService = networkService;
    networkService.onEvent((event) => {
      Eif (event.type === 'connected') {
        Object.keys(this.listenerRecord).forEach(domainName => this.register(domainName));
      }
    });
    this.networkService.subscribe(DOMAIN_DATA_CHANGE_TOPIC, (payload: DomainDataChangeRawEvent) => {
      this.listenerRecord[payload.domainName]?.forEach(l => {
        try {
          l(payload);
        } catch (e) {
          console.error(`Failed to handle domain data change event for domain ${payload.domainName}: ${e}`);
        }
      });
    });
    networkService.init();
  }
 
  private readonly register = (domainName: string): void => {
    this.networkService
      .send<DomainDataChangeSubscriberRequestPayload, DomainDataChangeSubscriberResponsePayload>(DOMAIN_DATA_CHANGE_TOPIC, {
        domainName: domainName,
        action: 'subscribe'
      })
      .then(payload => {
        if (payload.status === 'success') {
          console.log(`Successfully subscribed to domain ${domainName}`);
        } else E{
          console.error(`Failed to subscribe to domain ${domainName}`);
        }
      })
      .catch(e => {
        console.error(`Failed to subscribe to domain ${domainName}: ${e}`);
      });
  };
 
  private readonly unregister = (domainName: string): void => {
    this.networkService
      .send<DomainDataChangeSubscriberRequestPayload, DomainDataChangeSubscriberResponsePayload>(DOMAIN_DATA_CHANGE_TOPIC, {
        domainName: domainName,
        action: 'unsubscribe'
      })
      .then(payload => {
        if (payload.status === 'success') {
          console.log(`Successfully unsubscribed to domain ${domainName}`);
        } else E{
          console.error(`Failed to unsubscribe to domain ${domainName}`);
        }
      })
      .catch(e => {
        console.error(`Failed to unsubscribe to domain ${domainName}: ${e}`);
      });
  };
 
  public readonly subscribe = (domainName: string, listener: DomainDataChangeEventListener): UnsubscribeCallback => {
    if (this.listenerRecord[domainName]) {
      console.info(`Domain ${domainName} is already monitored`);
      this.listenerRecord[domainName].push(listener);
    } else {
      this.listenerRecord[domainName] = [listener];
      this.register(domainName);
    }
    return () => {
      const listeners = this.listenerRecord[domainName];
      Iif (!listeners) {
        return;
      }
      listeners.splice(listeners.findIndex(l => l === listener), 1);
      if (listeners.length === 0) {
        this.unregister(domainName);
        delete this.listenerRecord[domainName];
      }
    };
  };
 
}
 
let domainAutoRefreshService: DomainAutoRefreshService;
 
export const getDomainAutoRefreshService = (): DomainAutoRefreshService => {
  if (!domainAutoRefreshService) {
    domainAutoRefreshService = new DomainAutoRefreshService(getNetworkService());
  }
  return domainAutoRefreshService;
};