UNPKG

owltech

Version:
97 lines 3.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = require("events"); const http2 = require("http2"); const { HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_TE, HTTP2_HEADER_USER_AGENT } = http2.constants; /* setInterval and setTimeout only accept signed 32 bit integers. JS doesn't * have a constant for the max signed 32 bit integer, so this is a simple way * to calculate it */ const KEEPALIVE_TIME_MS = ~(1 << 31); const KEEPALIVE_TIMEOUT_MS = 20000; class Http2SubChannel extends events_1.EventEmitter { constructor(target, connectionOptions, userAgent, channelArgs) { super(); this.refCount = 0; this.keepaliveTimeMs = KEEPALIVE_TIME_MS; this.keepaliveTimeoutMs = KEEPALIVE_TIMEOUT_MS; this.session = http2.connect(target, connectionOptions); this.session.unref(); this.session.on('connect', () => { this.emit('connect'); }); this.session.on('close', () => { this.stopKeepalivePings(); this.emit('close'); }); this.session.on('error', () => { this.stopKeepalivePings(); this.emit('close'); }); this.userAgent = userAgent; if (channelArgs['grpc.keepalive_time_ms']) { this.keepaliveTimeMs = channelArgs['grpc.keepalive_time_ms']; } if (channelArgs['grpc.keepalive_timeout_ms']) { this.keepaliveTimeoutMs = channelArgs['grpc.keepalive_timeout_ms']; } this.keepaliveIntervalId = setTimeout(() => { }, 0); clearTimeout(this.keepaliveIntervalId); this.keepaliveTimeoutId = setTimeout(() => { }, 0); clearTimeout(this.keepaliveTimeoutId); } ref() { if (this.refCount === 0) { this.session.ref(); this.startKeepalivePings(); } this.refCount += 1; } unref() { this.refCount -= 1; if (this.refCount === 0) { this.session.unref(); this.stopKeepalivePings(); } } sendPing() { this.keepaliveTimeoutId = setTimeout(() => { this.emit('close'); }, this.keepaliveTimeoutMs); this.session.ping((err, duration, payload) => { clearTimeout(this.keepaliveTimeoutId); }); } /* TODO(murgatroid99): refactor subchannels so that keepalives can be handled * per subchannel */ startKeepalivePings() { this.keepaliveIntervalId = setInterval(() => { this.sendPing(); }, this.keepaliveTimeMs); this.sendPing(); } stopKeepalivePings() { clearInterval(this.keepaliveIntervalId); clearTimeout(this.keepaliveTimeoutId); } // Prerequisite: this subchannel is connected startCallStream(metadata, callStream) { const headers = metadata.toHttp2Headers(); headers[HTTP2_HEADER_AUTHORITY] = callStream.getHost(); headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; headers[HTTP2_HEADER_METHOD] = 'POST'; headers[HTTP2_HEADER_PATH] = callStream.getMethod(); headers[HTTP2_HEADER_TE] = 'trailers'; const http2Stream = this.session.request(headers); this.ref(); http2Stream.on('close', () => { this.unref(); }); callStream.attachHttp2Stream(http2Stream); } close() { this.session.close(); } } exports.Http2SubChannel = Http2SubChannel; //# sourceMappingURL=subchannel.js.map