tencentcloud-edgeone-migration-nodejs-v2
Version:
tencentcloud cdn config copy to edgeone
259 lines • 10.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PolarisGRPCClient = void 0;
const package_json_1 = require("@grpc/grpc-js/package.json");
const protoLoader = require("@grpc/proto-loader");
const path = require("path");
const semver = require("semver");
const __1 = require("../../../../..");
const utils_1 = require("../../../../../utils");
const adapter_1 = require("../../adapter");
const types_1 = require("../../types");
const utils_2 = require("../../utils");
const bidi_1 = require("./bidi");
/**
* `@grpc/grpc-js` 模块在导入时会校验当前环境是否满足其运行要求,
* 如不满足直接抛出异常,由于 `import` 语法所限无法进行捕获,
* 故在此采用 `require` 延迟加载。
*/
let grpcjs;
const kProtoFile = {
[types_1.ServiceType.Discover]: path.join(__dirname, "pb", "discover.proto"),
[types_1.ServiceType.Monitor]: path.join(__dirname, "pb", "monitor.proto"),
[types_1.ServiceType.Ratelimit]: path.join(__dirname, "pb", "ratelimit.proto")
};
const kDefaultOptions = {
/**
* 调用超时时间
*/
timeout: 10 * utils_1.kSeconds,
/**
* gRPC 配置项
*/
grpc: {
/**
* gRPC CallOptions 配置项
*/
call: {},
/**
* gRPC ChannelOptions 配置项
*/
channel: {}
}
};
const isIDiscoverRequest = (arg) => "type" in arg && "service" in arg;
const isIDiscoverResponse = (arg) => "type" in arg;
const isIdentifiablePacket = (arg) => Object.prototype.hasOwnProperty.call(arg, "id") || Object.prototype.hasOwnProperty.call(arg, "key");
const loadPackageDefinition = (type) => {
// eslint-disable-next-line @typescript-eslint/unbound-method
const { emitWarning } = process;
/*
* note:
* 由于 `@grpc/proto-loader` 在处理 options.includeDirs 时,
* 对于 `import google/protobuf/*.proto` 会抛出不正确的异常,
* 故在此屏蔽进行屏蔽,并在调用完 `loadSync` 后进行重置。
*/
process.emitWarning = () => { };
const packageDefinition = protoLoader.loadSync(kProtoFile[type], {
defaults: true,
keepCase: true,
longs: Number,
includeDirs: [utils_2.kProtoPath[type]]
});
process.emitWarning = emitWarning;
return grpcjs.loadPackageDefinition(packageDefinition).v1;
};
class PolarisGRPCClient extends adapter_1.PolarisServerAdapter {
constructor(remotes, options) {
super(remotes, options);
this.name = "PolarisGRPCClient";
this.protocol = PolarisGRPCClient.protocol;
this.format = utils_2.ProtobufFormat.Original;
this.options = Object.assign(Object.assign(Object.assign(Object.assign({}, this.options), kDefaultOptions), options), { grpc: Object.assign(Object.assign(Object.assign({}, this.options.grpc), kDefaultOptions.grpc), options === null || options === void 0 ? void 0 : options.grpc) });
if (!PolarisGRPCClient.isSupported()) {
throw new __1.PluginError(`grpc client only works on Node ${package_json_1.engines.node}`);
}
if (!grpcjs) {
grpcjs = require("@grpc/grpc-js"); // eslint-disable-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
}
this.clientConstructor = {
[types_1.ServiceType.Discover]: loadPackageDefinition(types_1.ServiceType.Discover).PolarisGRPC,
[types_1.ServiceType.Monitor]: loadPackageDefinition(types_1.ServiceType.Monitor).GrpcAPI,
[types_1.ServiceType.Ratelimit]: loadPackageDefinition(types_1.ServiceType.Ratelimit).RateLimitGRPC
};
}
static isSupported() {
return semver.satisfies(process.versions.node, package_json_1.engines.node);
}
box(value) {
if (value === null || typeof value === "undefined") {
return value;
}
return {
value
};
}
unbox(value, defaultValue) {
const val = value;
if (val && typeof val.value !== "undefined" && val.value !== null) {
return val.value;
}
if (typeof defaultValue === "function") {
return defaultValue();
}
return defaultValue;
}
// #region #AOP#
/**
* 实例化 Service Client,可重载此方法实现差异化配置
* @param address 远端地址
* @param type 远端类型
* @param ServiceClient Service Client Class,函数必须返回它的实例
* @param credentials grpc.credentials
*/
instantiateServiceClient(address, type, ServiceClient, credentials) {
return new ServiceClient(address, credentials.createInsecure(), this.options.grpc.channel);
}
/**
* 获取 grpc.CallOptions 配置,可重载此方法实现差异化配置
* @param address 远端地址
* @param method 方法名
* @param streaming 是否为 Bidi Stream
*/
getCallOptions(address, method, streaming) {
const { options: { timeout, grpc: { call: callOptions } } } = this;
if (streaming) {
return callOptions;
}
return Object.assign(Object.assign({}, callOptions), { deadline: Date.now() + timeout });
}
// #endregion
buildClient(address, type) {
const { logger, options: { timeout } } = this;
const { transaction } = logger;
logger.trace("Plugins" /* Plugins */, this.name, "buildClient", transaction, "remote address is", address, "and type is", type);
const ServiceClient = this.clientConstructor[type]; // eslint-disable-line @typescript-eslint/naming-convention
const grpcClient = this.instantiateServiceClient(address, type, ServiceClient, grpcjs.credentials);
const client = Object.create(null);
const bidi = [];
for (const name of Object.keys(ServiceClient.service)) {
const { requestStream, responseStream, originalName } = ServiceClient.service[name];
const method = (originalName || name);
if (!requestStream && !responseStream) {
/* Unary */
client[method] = ((request) => new Promise((resolve, reject) => {
grpcClient[name](request, this.getCallOptions(address, name, false), (err, value) => {
if (err) {
reject(err);
}
else {
resolve(value);
}
});
}));
}
else if (requestStream && responseStream) {
/* Bidi */
const caller = new bidi_1.StreamCaller(grpcClient[name]
.bind(grpcClient, this.getCallOptions(address, name, true)), this.keyGenerator.bind(this), timeout);
client[method] = ((request) => caller.request(request));
bidi.push(caller);
}
else {
(0, utils_1.UNREACHABLE)();
}
}
client.close = () => {
logger.trace("Plugins" /* Plugins */, this.name, "buildClient", transaction, "close all client");
bidi.forEach(caller => caller.close());
/*
* avoid GRPC Error:
* 14 UNAVAILABLE: No connection established
*/
try {
grpcClient.close();
}
catch (e) {
logger.trace("Plugins" /* Plugins */, this.name, "buildClient", transaction, "close grpc client exception with", e);
logger.error(`[${this.name}] [close]`, e);
}
};
return client;
}
requestKeyGenerator(request) {
var _a;
if (isIDiscoverRequest(request) && request.service) {
const { namespace, name } = request.service;
return {
keys: [namespace, name],
type: request.type
};
}
if (isIdentifiablePacket(request)) {
return {
keys: [(_a = request.id) !== null && _a !== void 0 ? _a : request.key],
type: "*"
};
}
(0, utils_1.UNREACHABLE)();
}
responseKeyGenerator(response) {
var _a;
if (isIDiscoverResponse(response)) {
/** intentional convert */
switch (response.type) {
case types_1.DiscoverRequestType.INSTANCE: // [[fallthrough]]
case types_1.DiscoverRequestType.ROUTING: // [[fallthrough]]
case types_1.DiscoverRequestType.RATE_LIMIT: {
if (response.service) {
const { namespace, name } = response.service;
return {
keys: [namespace, name],
type: response.type
};
}
(0, utils_1.UNREACHABLE)();
}
case types_1.DiscoverRequestType.CLUSTER: // [[fallthrough]]
case types_1.DiscoverRequestType.UNKNOWN: // [[fallthrough]]
default: {
(0, utils_1.UNREACHABLE)();
}
}
(0, utils_1.UNREACHABLE)(); /** Stub */
}
if (isIdentifiablePacket(response)) {
return {
keys: [(_a = response.id) !== null && _a !== void 0 ? _a : response.key],
type: "*"
};
}
(0, utils_1.UNREACHABLE)();
}
keyGenerator(direction, packet) {
let type;
let keys;
switch (direction) {
case bidi_1.PacketDirection.Request: {
({ keys, type } = this.requestKeyGenerator(packet));
break;
}
case bidi_1.PacketDirection.Response: {
({ keys, type } = this.responseKeyGenerator(packet));
break;
}
default: {
(0, utils_1.UNREACHABLE)();
}
}
keys = keys.map(key => this.unbox(key, typeof key === "string" ? key : ""));
if (keys.every(key => key === "") || type === undefined) {
(0, utils_1.UNREACHABLE)();
}
return `${type}.${keys.join(".")}`;
}
}
exports.PolarisGRPCClient = PolarisGRPCClient;
PolarisGRPCClient.protocol = "grpc";
PolarisGRPCClient.port = 8081;
//# sourceMappingURL=index.js.map