import { Inject, Injectable, Type } from '@angular/core'; import * as jspb from 'google-protobuf'; import * as nats from 'nats.ws'; import { HEADER_CLIENT } from 'app/modules/protobuf/c2se/core/network_pb'; import { Client } from 'app/modules/protobuf/models/core/network_pb'; import { ModuleConfig } from '../config/module-config'; import { _MODULE_CONFIG } from '../config/token'; type DeserializeConstructor = { new (): T; deserializeBinary(this: DeserializeConstructor, bytes: Uint8Array): T; }; const NAME_GET_ERROR = 'getError'; const NAME_GET_RESULT = 'getResult'; @Injectable({ providedIn: 'root', }) export class NatsService { private __conn?: nats.NatsConnection; /** * Constructor */ constructor(@Inject(_MODULE_CONFIG) private __config: ModuleConfig) {} // ----------------------------------------------------------------------------------------------------- // @ Accessors // ----------------------------------------------------------------------------------------------------- get connection(): nats.NatsConnection | undefined { return this.__conn; } // ----------------------------------------------------------------------------------------------------- // @ Public methods // ----------------------------------------------------------------------------------------------------- connect(): Promise { return new Promise((resolve, reject) => { if (!!this.__conn) { return resolve(); } nats .connect(this.__config.connectionOptions) .then((conn) => { console.log('NATS connected', conn.info?.client_ip); this.__conn = conn; resolve(); }) .catch((e) => { reject(e); }); }); } request( subject: string, req: Uint8Array, deserialize: (data: Uint8Array) => any, opts?: nats.RequestOptions | undefined ): Promise { return new Promise((resolve, reject) => { let c = new Client(); c.setClientIp(this.__conn?.info?.client_ip + ''); c.setSessionId(''); c.setSiteUrl(''); let _opts: nats.RequestOptions = !!opts ? opts : { timeout: 3000 }; if (!_opts.headers) { _opts.headers = nats.headers(); } var decoder = new TextDecoder('utf8'); _opts.headers.append( HEADER_CLIENT, btoa(decoder.decode(c.serializeBinary())) ); this.__conn?.request(subject, req, _opts).then((msg) => { let res = deserialize(msg.data); let get_error = (res as any)[NAME_GET_ERROR]; if (!!get_error) { let error = get_error.call(res); if (!!error) { return reject(error); } } let get_result = (res as any)[NAME_GET_RESULT]; if (!!get_result) { let result = get_result.call(res); if (!result) { return reject('result is not exist'); } return resolve(result); } return reject('protocol error'); }); }); } }