1 | ;
|
2 | var __extends = (this && this.__extends) || (function () {
|
3 | var extendStatics = Object.setPrototypeOf ||
|
4 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
5 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
6 | return function (d, b) {
|
7 | extendStatics(d, b);
|
8 | function __() { this.constructor = d; }
|
9 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
10 | };
|
11 | })();
|
12 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
13 | return new (P || (P = Promise))(function (resolve, reject) {
|
14 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
15 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
16 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
17 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
18 | });
|
19 | };
|
20 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
21 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
22 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
23 | function verb(n) { return function (v) { return step([n, v]); }; }
|
24 | function step(op) {
|
25 | if (f) throw new TypeError("Generator is already executing.");
|
26 | while (_) try {
|
27 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
28 | if (y = 0, t) op = [op[0] & 2, t.value];
|
29 | switch (op[0]) {
|
30 | case 0: case 1: t = op; break;
|
31 | case 4: _.label++; return { value: op[1], done: false };
|
32 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
33 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
34 | default:
|
35 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
36 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
37 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
38 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
39 | if (t[2]) _.ops.pop();
|
40 | _.trys.pop(); continue;
|
41 | }
|
42 | op = body.call(thisArg, _);
|
43 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
44 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
45 | }
|
46 | };
|
47 | Object.defineProperty(exports, "__esModule", { value: true });
|
48 | /**
|
49 | * 研究阿里云的OTS表格设计将session、cache、user三种缓存信息算法构建在此之上。
|
50 | */
|
51 | var TableStore = require('tablestore');
|
52 | var Long = TableStore.Long;
|
53 | var _ = require('lodash');
|
54 | var NoSqlInterface = /** @class */ (function () {
|
55 | function NoSqlInterface(table, config) {
|
56 | if (config === void 0) { config = 'default'; }
|
57 | }
|
58 | return NoSqlInterface;
|
59 | }());
|
60 | // export async function test() {
|
61 | // const ots = new NoSqlAliyunTablestore('session_test3')
|
62 | // // let out = await ots.create(60)
|
63 | // // FIXME 首次创建表需要有一定的系统延迟时间,需要放到install过程中进行维护。
|
64 | // // let out = await ots.insert('x', {a: 'aaa', b: {value: 'bbbb', timestamp: Date.now()}})
|
65 | // // let out = await ots.update('x', {a: 'aaa2', b: 'bbb2'})
|
66 | // // let out = await ots.update('x', {a: null, b: 1529666053100})
|
67 | // // let out = await ots.delete('x')
|
68 | //
|
69 | // let out
|
70 | // // out = await ots.insert('x', {a: 'aaa', b: {value: 'bbbb', timestamp: Date.now()}})
|
71 | // // out = await ots.query('x') // 取全部的字段
|
72 | // // out = await ots.query('x', ['a']) // 取部分字段
|
73 | // // out = await ots.query('y') // 取不存在的主键
|
74 | //
|
75 | // // out = await ots.create(24*60*60,2)
|
76 | // // out = await ots.insert('z', {a: 'aaa'+Date(), b: {value: 'bbbb'+Date(), timestamp: Date.now()}})
|
77 | // // out = await ots.update('z', {a: 'aaa'+Date(), b: 'bbbb'+Date()})
|
78 | // // out = await ots.query('z', null, 2)
|
79 | // out = await ots.query('z', null, 1)
|
80 | // // 用最佳方案去实现字段
|
81 | // return out
|
82 | // }
|
83 | // 对于阿里云tablestore的单表功能简单封装处理(一个主键并作为分区唯一区分一个记录,仅用于缓存功能实现。
|
84 | // 封装特点:每个记录一条主键并作为分区,每个记录有无数个kv值可供配置,每个kv值都有一个时间戳超时时间在表上单独配置。)
|
85 | var NoSqlAliyunTablestore = /** @class */ (function (_super) {
|
86 | __extends(NoSqlAliyunTablestore, _super);
|
87 | function NoSqlAliyunTablestore(table, config) {
|
88 | if (config === void 0) { config = 'default'; }
|
89 | var _this = _super.call(this, table, config) || this;
|
90 | var instances = xconfig('plugins.nosql');
|
91 | xassert(instances && _.isPlainObject(instances) && config in instances, ERR$CONFIG, { instances: instances });
|
92 | _this._table = table;
|
93 | _this._schema = {
|
94 | KEYS: {
|
95 | id: 'string' // 表的唯一记录主键值同时也是分区
|
96 | }
|
97 | };
|
98 | _this._client = new TableStore.Client({
|
99 | accessKeyId: instances[config].OTS_ACCESS_KEY_ID,
|
100 | secretAccessKey: instances[config].OTS_SECRETE_ACCESS_KEY,
|
101 | endpoint: instances[config].OTS_ENDPOINT,
|
102 | instancename: instances[config].OTS_INSTANCENAME
|
103 | });
|
104 | return _this;
|
105 | }
|
106 | Object.defineProperty(NoSqlAliyunTablestore.prototype, "table", {
|
107 | set: function (value) {
|
108 | this._table = value;
|
109 | },
|
110 | enumerable: true,
|
111 | configurable: true
|
112 | });
|
113 | // 约定所有表都需要有自增主键id作为内部唯一标识码,其余三个主键必须全部为字符串。(后端需要扩展int和date基本数据类型以及操作符重载实现优化开发)
|
114 | // 属性字段可以根据业务演变任意的扩展增加由业务代码对于老数据不存在新增字段值的情况做兼容处理
|
115 | NoSqlAliyunTablestore.prototype.insert = function (id, kvt) {
|
116 | return __awaiter(this, void 0, void 0, function () {
|
117 | var _a, _b, __this__, params, k;
|
118 | return __generator(this, function (_c) {
|
119 | xassert(Object.keys(kvt).length <= 128); // 规避跨行限制总计属性128个
|
120 | __this__ = this;
|
121 | params = {
|
122 | tableName: this._table,
|
123 | // 插入的时候需要确保不存在对应的数据以防止出错
|
124 | condition: new TableStore.Condition(TableStore.RowExistenceExpectation.EXPECT_NOT_EXIST, null),
|
125 | primaryKey: [],
|
126 | attributeColumns: [],
|
127 | // 按照下面数据格式进行schema定义的验证以及数据类型转换
|
128 | // primaryKey: [{'gid': Long.fromNumber(20013)}, {'uid': Long.fromNumber(20013)}],
|
129 | // attributeColumns: [
|
130 | // {'col1': '表格存储'},
|
131 | // {'col2': '2', 'timestamp': currentTimeStamp}, // 允许修改时间戳乐观锁功能实现暂不支持
|
132 | // {'col3': 3.1},
|
133 | // {'col4': -0.32},
|
134 | // {'col5': Long.fromNumber(123456789)}
|
135 | // ],
|
136 | // primaryKey: [
|
137 | // {'short_id': 'pk1'},
|
138 | // {[AUTO_KEY_NAME]: TableStore.PK_AUTO_INCR}
|
139 | // ],
|
140 | // attributeColumns: [
|
141 | // {'appcode': 'app1'}
|
142 | // ],
|
143 | returnContent: { returnType: TableStore.ReturnType.Primarykey }
|
144 | };
|
145 | // 拼接主键以及属性字段值
|
146 | params.primaryKey = [{ 'id': id }];
|
147 | for (k in kvt) {
|
148 | xassert(k != 'id' && k != 'timestamp'); // 两个预留内部标识符不可作为属性名
|
149 | if (_.isString(kvt[k])) {
|
150 | params.attributeColumns.push((_a = {},
|
151 | _a[k] = kvt[k],
|
152 | _a));
|
153 | }
|
154 | else {
|
155 | params.attributeColumns.push((_b = {},
|
156 | _b[k] = kvt[k]['value'],
|
157 | _b.timestamp = kvt[k]['timestamp'],
|
158 | _b));
|
159 | }
|
160 | }
|
161 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
162 | try {
|
163 | __this__._client.putRow(params, function (err, out) {
|
164 | if (err) {
|
165 | xthrow(new Error(err), reject, { params: params, out: out });
|
166 | return;
|
167 | }
|
168 | // 正常返回的数据格式
|
169 | //{"consumed":{"capacity_unit":{"read":0,"write":1}},"row":{
|
170 | // "primaryKey":[{"name":"short_id","value":"abcd"},{"name":"id","value":1520765502347000}],
|
171 | // "attributes":[]},
|
172 | // "RequestId":"00056720-cf8d-d4a8-8ae8-970a17894ce6"}
|
173 | resolve(out);
|
174 | });
|
175 | }
|
176 | catch (err) {
|
177 | xthrow(err, reject);
|
178 | }
|
179 | })];
|
180 | });
|
181 | });
|
182 | };
|
183 | NoSqlAliyunTablestore.prototype.update = function (id, kvt) {
|
184 | return __awaiter(this, void 0, void 0, function () {
|
185 | return __generator(this, function (_a) {
|
186 | switch (_a.label) {
|
187 | case 0: return [4 /*yield*/, this._update_or_replace(id, kvt, false)];
|
188 | case 1: return [2 /*return*/, _a.sent()];
|
189 | }
|
190 | });
|
191 | });
|
192 | };
|
193 | NoSqlAliyunTablestore.prototype.replace = function (id, kvt) {
|
194 | return __awaiter(this, void 0, void 0, function () {
|
195 | return __generator(this, function (_a) {
|
196 | switch (_a.label) {
|
197 | case 0: return [4 /*yield*/, this._update_or_replace(id, kvt, true)];
|
198 | case 1: return [2 /*return*/, _a.sent()];
|
199 | }
|
200 | });
|
201 | });
|
202 | };
|
203 | // 条件更新必须要填写主键记录值(仅仅允许更新属性字段而主键字段是不允许更新的,
|
204 | // 整列更新和删除列属于运维操作禁止应用中使用需要单独接口以及权限认证)
|
205 | NoSqlAliyunTablestore.prototype._update_or_replace = function (id, kvt, isIgnoreRowNonExist) {
|
206 | if (isIgnoreRowNonExist === void 0) { isIgnoreRowNonExist = false; }
|
207 | return __awaiter(this, void 0, void 0, function () {
|
208 | var _a, _b, __this__, params, PUT, DELETE, DELETE_ALL, k;
|
209 | return __generator(this, function (_c) {
|
210 | xassert(Object.keys(kvt).length > 0 && Object.keys(kvt).length <= 128); // 规避跨行限制总计属性128个
|
211 | __this__ = this;
|
212 | params = {
|
213 | tableName: this._table,
|
214 | condition: new TableStore.Condition(isIgnoreRowNonExist ?
|
215 | TableStore.RowExistenceExpectation.IGNORE :
|
216 | TableStore.RowExistenceExpectation.EXPECT_EXIST, null),
|
217 | primaryKey: [{ id: id }],
|
218 | // updateOfAttributeColumns: [{'PUT': [{'col1': 'test6'}]}]
|
219 | updateOfAttributeColumns: []
|
220 | // updateOfAttributeColumns: [
|
221 | // { 'PUT': [{ 'col4': Long.fromNumber(4) }, { 'col5': '5' }, { 'col6': Long.fromNumber(6) }] },
|
222 | // { 'DELETE': [{ 'col1': Long.fromNumber(1496826473186) }] }, // 删除指定时间戳版本数据
|
223 | // { 'DELETE_ALL': ['col2'] } // 删除所有版本的字段数据
|
224 | // ]
|
225 | };
|
226 | PUT = [];
|
227 | DELETE = [];
|
228 | DELETE_ALL = [];
|
229 | for (k in kvt) {
|
230 | // 如果变量值为null类型则表示删除对应的字段值,如果为整数表示删除指定时间戳版本,否则表示添加或更新对应字段值。
|
231 | if (!kvt[k]) {
|
232 | DELETE_ALL.push(k);
|
233 | }
|
234 | else if (_.isInteger(kvt[k])) {
|
235 | DELETE.push((_a = {}, _a[k] = Long.fromNumber(kvt[k]), _a));
|
236 | }
|
237 | else if (_.isString(kvt[k])) {
|
238 | PUT.push((_b = {}, _b[k] = kvt[k], _b));
|
239 | }
|
240 | else {
|
241 | xassert(false, ERR$PARAM, { id: id, kvt: kvt });
|
242 | }
|
243 | }
|
244 | if (PUT.length > 0)
|
245 | params.updateOfAttributeColumns.push({ PUT: PUT });
|
246 | if (DELETE.length > 0)
|
247 | params.updateOfAttributeColumns.push({ DELETE: DELETE });
|
248 | if (DELETE_ALL.length > 0)
|
249 | params.updateOfAttributeColumns.push({ DELETE_ALL: DELETE_ALL });
|
250 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
251 | try {
|
252 | __this__._client.updateRow(params, function (err, data) {
|
253 | if (err) {
|
254 | xthrow(new Error(err), reject, { params: params, data: data });
|
255 | return;
|
256 | }
|
257 | resolve();
|
258 | });
|
259 | }
|
260 | catch (err) {
|
261 | xthrow(err, reject);
|
262 | }
|
263 | })];
|
264 | });
|
265 | });
|
266 | };
|
267 | // 以主键作为条件删除记录值
|
268 | NoSqlAliyunTablestore.prototype.delete = function (id) {
|
269 | return __awaiter(this, void 0, void 0, function () {
|
270 | var __this__, params;
|
271 | return __generator(this, function (_a) {
|
272 | __this__ = this;
|
273 | params = {
|
274 | tableName: this._table,
|
275 | condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),
|
276 | // primaryKey: [{ 'gid': Long.fromNumber(8) }, { 'uid': Long.fromNumber(80) }]
|
277 | primaryKey: [{ id: id }]
|
278 | };
|
279 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
280 | try {
|
281 | __this__._client.deleteRow(params, function (err, data) {
|
282 | if (err) {
|
283 | xthrow(new Error(err), reject, { params: params, data: data });
|
284 | return;
|
285 | }
|
286 | resolve();
|
287 | });
|
288 | }
|
289 | catch (err) {
|
290 | xthrow(err, reject);
|
291 | }
|
292 | })];
|
293 | });
|
294 | });
|
295 | };
|
296 | // 范围查询需要数据自动同步到opensearch进行索引同步后进行各种复杂的查询操作实现免运维系统的实现
|
297 | // 单表逻辑条件的简单and与equal的查询,返回满足条件的第一条记录 (合并为一个查询兼容mongodb的查询扩展)
|
298 | NoSqlAliyunTablestore.prototype.query = function (id, keys, max_version) {
|
299 | if (keys === void 0) { keys = null; }
|
300 | if (max_version === void 0) { max_version = 1; }
|
301 | return __awaiter(this, void 0, void 0, function () {
|
302 | var __this__, params;
|
303 | return __generator(this, function (_a) {
|
304 | __this__ = this;
|
305 | params = {
|
306 | tableName: this._table,
|
307 | columnsToGet: keys,
|
308 | // columns_to_get 获取期望的列最多128个一次获取总数,应用上应该将KEY视为分组总数。
|
309 | // 如何规避宽表的分页限制?? FIXME 先从应用上规避限制一个应用最多不超过128个属性,通过JSON进行扩展存储。
|
310 | primaryKey: [{ id: id }],
|
311 | // primaryKey: [{'gid': Long.fromNumber(20013)}, {'uid': Long.fromNumber(20013)}],
|
312 | columnFilter: null,
|
313 | maxVersions: max_version,
|
314 | };
|
315 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
316 | __this__._client.getRow(params, function (err, data) {
|
317 | if (err) {
|
318 | xthrow(new Error(err), reject, { params: params, data: data });
|
319 | return;
|
320 | }
|
321 | // 返回数据格式类型进行转换处理
|
322 | // {"consumed":{"capacity_unit":{"read":1,"write":0}},
|
323 | // "row":{"primaryKey":[{"name":"gid","value":20013},{"name":"uid","value":20013}],
|
324 | // "attributes":[{"columnName":"col1","columnValue":"表格存储","timestamp":1520734520286},
|
325 | // {"columnName":"col2","columnValue":"2","timestamp":1520734520064},
|
326 | // {"columnName":"col3","columnValue":3.1,"timestamp":1520734520286},
|
327 | // {"columnName":"col4","columnValue":-0.32,"timestamp":1520734520286},
|
328 | // {"columnName":"col5","columnValue":123456789,"timestamp":1520734520286}]
|
329 | // },
|
330 | // "next_token":null,"RequestId":"00056719-e2ad-73b1-dbd8-970a19522f4b"}
|
331 | // 将数据结果进行转换处理合并为一个普通对象给应用使用
|
332 | try {
|
333 | var out = {};
|
334 | if (!data.row) {
|
335 | return resolve(null);
|
336 | }
|
337 | if (data.row.primaryKey) {
|
338 | for (var k in data.row.primaryKey) {
|
339 | out[data.row.primaryKey[k].name] = data.row.primaryKey[k].value;
|
340 | }
|
341 | }
|
342 | if (data.row.attributes) {
|
343 | for (var k in data.row.attributes) {
|
344 | out[data.row.attributes[k].columnName] = data.row.attributes[k].columnValue;
|
345 | }
|
346 | }
|
347 | // xlog(data) // TODO 当存在多个版本数据的时候解析不正确,应该是多个版本的属性值字段的组合才正确。
|
348 | resolve(_.isEmpty(out) ? null : out);
|
349 | }
|
350 | catch (err) {
|
351 | xthrow(new Error(err), reject, { params: params, data: data });
|
352 | return;
|
353 | }
|
354 | });
|
355 | })];
|
356 | });
|
357 | });
|
358 | };
|
359 | // 销毁表
|
360 | NoSqlAliyunTablestore.prototype.destroy = function () {
|
361 | return __awaiter(this, void 0, void 0, function () {
|
362 | var err_1, i, out, err_2;
|
363 | return __generator(this, function (_a) {
|
364 | switch (_a.label) {
|
365 | case 0:
|
366 | _a.trys.push([0, 2, , 3]);
|
367 | return [4 /*yield*/, this._destroy()];
|
368 | case 1:
|
369 | _a.sent();
|
370 | return [3 /*break*/, 3];
|
371 | case 2:
|
372 | err_1 = _a.sent();
|
373 | return [2 /*return*/];
|
374 | case 3:
|
375 | i = 0;
|
376 | _a.label = 4;
|
377 | case 4:
|
378 | if (!(i < 100)) return [3 /*break*/, 9];
|
379 | _a.label = 5;
|
380 | case 5:
|
381 | _a.trys.push([5, 6, , 8]);
|
382 | out = this.describe();
|
383 | xlog(out);
|
384 | return [3 /*break*/, 8];
|
385 | case 6:
|
386 | err_2 = _a.sent();
|
387 | return [4 /*yield*/, xsleep(100)];
|
388 | case 7:
|
389 | _a.sent();
|
390 | return [3 /*break*/, 9];
|
391 | case 8:
|
392 | i++;
|
393 | return [3 /*break*/, 4];
|
394 | case 9: return [2 /*return*/];
|
395 | }
|
396 | });
|
397 | });
|
398 | };
|
399 | NoSqlAliyunTablestore.prototype._destroy = function () {
|
400 | return __awaiter(this, void 0, void 0, function () {
|
401 | var __this__, params;
|
402 | return __generator(this, function (_a) {
|
403 | __this__ = this;
|
404 | params = {
|
405 | tableName: this._table
|
406 | };
|
407 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
408 | __this__._client.deleteTable(params, function (err, data) {
|
409 | if (err) {
|
410 | xthrow(new Error(err), reject, { params: params });
|
411 | return;
|
412 | }
|
413 | resolve();
|
414 | });
|
415 | })];
|
416 | });
|
417 | });
|
418 | };
|
419 | // 创建表
|
420 | NoSqlAliyunTablestore.prototype.create = function (timeout, max_versions) {
|
421 | if (timeout === void 0) { timeout = -1; }
|
422 | if (max_versions === void 0) { max_versions = 1; }
|
423 | return __awaiter(this, void 0, void 0, function () {
|
424 | var i, out, err_3;
|
425 | return __generator(this, function (_a) {
|
426 | switch (_a.label) {
|
427 | case 0: return [4 /*yield*/, this._create(timeout, max_versions)
|
428 | // 10秒钟等待超时创建表正常完成
|
429 | ];
|
430 | case 1:
|
431 | _a.sent();
|
432 | i = 0;
|
433 | _a.label = 2;
|
434 | case 2:
|
435 | if (!(i < 100)) return [3 /*break*/, 8];
|
436 | _a.label = 3;
|
437 | case 3:
|
438 | _a.trys.push([3, 4, , 6]);
|
439 | out = this.describe();
|
440 | xlog(out);
|
441 | return [3 /*break*/, 6];
|
442 | case 4:
|
443 | err_3 = _a.sent();
|
444 | return [4 /*yield*/, xsleep(100)];
|
445 | case 5:
|
446 | _a.sent();
|
447 | return [3 /*break*/, 7];
|
448 | case 6: return [3 /*break*/, 8];
|
449 | case 7:
|
450 | i++;
|
451 | return [3 /*break*/, 2];
|
452 | case 8: return [2 /*return*/];
|
453 | }
|
454 | });
|
455 | });
|
456 | };
|
457 | NoSqlAliyunTablestore.prototype._create = function (timeout, max_versions) {
|
458 | if (timeout === void 0) { timeout = -1; }
|
459 | if (max_versions === void 0) { max_versions = 1; }
|
460 | return __awaiter(this, void 0, void 0, function () {
|
461 | var __this__, params, k, obj, out;
|
462 | return __generator(this, function (_a) {
|
463 | switch (_a.label) {
|
464 | case 0:
|
465 | // OTS最长超时时间为1天的兼容处理
|
466 | if (timeout != -1 && timeout < 86400) {
|
467 | timeout = 86400;
|
468 | }
|
469 | __this__ = this;
|
470 | params = {
|
471 | tableMeta: {
|
472 | tableName: this._table,
|
473 | primaryKey: [],
|
474 | },
|
475 | reservedThroughput: {
|
476 | capacityUnit: {
|
477 | read: 0,
|
478 | write: 0
|
479 | }
|
480 | },
|
481 | tableOptions: {
|
482 | timeToLive: timeout,
|
483 | maxVersions: max_versions,
|
484 | }
|
485 | };
|
486 | // 自动转换schema定义为OTS的数据结构
|
487 | for (k in this._schema.KEYS) {
|
488 | obj = {
|
489 | name: k,
|
490 | type: _.upperCase(this._schema.KEYS[k])
|
491 | };
|
492 | // if (k == AUTO_KEY_NAME) {
|
493 | // obj['option'] = 'AUTO_INCREMENT'
|
494 | // }
|
495 | params.tableMeta.primaryKey.push(obj);
|
496 | }
|
497 | return [4 /*yield*/, new Promise(function (resolve, reject) {
|
498 | __this__._client.createTable(params, function (err, data) {
|
499 | if (err) {
|
500 | xthrow(new Error(err), reject, { params: params, data: data });
|
501 | return;
|
502 | }
|
503 | resolve();
|
504 | });
|
505 | })
|
506 | // FIXME 表创建后有一定的延时时间才能生效,需要维持一定的等待时间确保正常执行完成。
|
507 | // TODO 延时算法自动完成时间戳的处理。
|
508 | ];
|
509 | case 1:
|
510 | out = _a.sent();
|
511 | // FIXME 表创建后有一定的延时时间才能生效,需要维持一定的等待时间确保正常执行完成。
|
512 | // TODO 延时算法自动完成时间戳的处理。
|
513 | return [2 /*return*/, out];
|
514 | }
|
515 | });
|
516 | });
|
517 | };
|
518 | // 查询当前表的描述信息
|
519 | NoSqlAliyunTablestore.prototype.describe = function () {
|
520 | return __awaiter(this, void 0, void 0, function () {
|
521 | var __this__, params;
|
522 | return __generator(this, function (_a) {
|
523 | __this__ = this;
|
524 | params = {
|
525 | tableName: this._table
|
526 | };
|
527 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
528 | __this__._client.describeTable(params, function (err, data) {
|
529 | if (err) {
|
530 | xthrow(new Error(err), reject, { params: params });
|
531 | return;
|
532 | }
|
533 | resolve(data);
|
534 | });
|
535 | })];
|
536 | });
|
537 | });
|
538 | };
|
539 | // 表配置信息的更新处理(时间戳以及版本号)
|
540 | NoSqlAliyunTablestore.prototype.change = function (param) {
|
541 | return __awaiter(this, void 0, void 0, function () {
|
542 | var __this__, params;
|
543 | return __generator(this, function (_a) {
|
544 | __this__ = this;
|
545 | params = {
|
546 | tableName: this._table,
|
547 | tableOptions: {
|
548 | // 保存的最大版本数, 设置为1即代表每列上最多保存一个版本(保存最新的版本).
|
549 | maxVersions: param.maxVersions ? param.maxVersions : 1,
|
550 | // 数据的过期时间, 单位秒, -1代表永不过期. 假如设置过期时间为一年, 即为 365 * 24 * 3600
|
551 | timeToLive: param.timeoutSeconds ? param.timeoutSeconds : -1,
|
552 | },
|
553 | reservedThroughput: {
|
554 | capacityUnit: {
|
555 | // 为了提升并发度确保预留最小读写数量的配置避免服务共享可能产生的资源竞争不稳定问题
|
556 | read: param.reservedThroughputRead ? param.reservedThroughputRead : 0,
|
557 | write: param.reservedThroughputWrite ? param.reservedThroughputWrite : 0,
|
558 | }
|
559 | },
|
560 | };
|
561 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
562 | __this__._client.updateTable(params, function (err, data) {
|
563 | if (err) {
|
564 | xthrow(new Error(err), reject, { params: params });
|
565 | return;
|
566 | }
|
567 | resolve(data);
|
568 | });
|
569 | })];
|
570 | });
|
571 | });
|
572 | };
|
573 | // 重置表
|
574 | NoSqlAliyunTablestore.prototype.reset = function () {
|
575 | return __awaiter(this, void 0, void 0, function () {
|
576 | var err_4;
|
577 | return __generator(this, function (_a) {
|
578 | switch (_a.label) {
|
579 | case 0:
|
580 | _a.trys.push([0, 2, , 3]);
|
581 | return [4 /*yield*/, this.destroy()];
|
582 | case 1:
|
583 | _a.sent();
|
584 | return [3 /*break*/, 3];
|
585 | case 2:
|
586 | err_4 = _a.sent();
|
587 | return [3 /*break*/, 3];
|
588 | case 3: return [4 /*yield*/, this.create()];
|
589 | case 4:
|
590 | _a.sent();
|
591 | return [2 /*return*/];
|
592 | }
|
593 | });
|
594 | });
|
595 | };
|
596 | return NoSqlAliyunTablestore;
|
597 | }(NoSqlInterface));
|
598 | exports.NoSqlAliyunTablestore = NoSqlAliyunTablestore;
|
599 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxpeXVuX290cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFsaXl1bl9vdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7R0FFRztBQUNILElBQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN4QyxJQUFNLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFBO0FBQzVCLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUUzQjtJQUNJLHdCQUFZLEtBQWEsRUFBRSxNQUFpQztRQUFqQyx1QkFBQSxFQUFBLGtCQUFpQztJQUM1RCxDQUFDO0lBaUNMLHFCQUFDO0FBQUQsQ0FBQyxBQW5DRCxJQW1DQztBQUVELGlDQUFpQztBQUNqQyw2REFBNkQ7QUFDN0Qsd0NBQXdDO0FBQ3hDLHFEQUFxRDtBQUNyRCxnR0FBZ0c7QUFDaEcsaUVBQWlFO0FBQ2pFLHNFQUFzRTtBQUN0RSx5Q0FBeUM7QUFDekMsRUFBRTtBQUNGLGNBQWM7QUFDZCw0RkFBNEY7QUFDNUYsK0NBQStDO0FBQy9DLHFEQUFxRDtBQUNyRCxnREFBZ0Q7QUFDaEQsRUFBRTtBQUNGLDRDQUE0QztBQUM1QywwR0FBMEc7QUFDMUcsMEVBQTBFO0FBQzFFLDZDQUE2QztBQUM3QywwQ0FBMEM7QUFDMUMsb0JBQW9CO0FBQ3BCLGlCQUFpQjtBQUNqQixJQUFJO0FBRUosMERBQTBEO0FBQzFELCtEQUErRDtBQUMvRDtJQUEyQyx5Q0FBYztJQVNyRCwrQkFBWSxLQUFhLEVBQUUsTUFBMEI7UUFBMUIsdUJBQUEsRUFBQSxrQkFBMEI7UUFBckQsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxDQUFDLFNBaUJ2QjtRQWhCRyxJQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7UUFDMUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxDQUFDLENB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RCxDQUFDLEFBamFELENBQTJDLGNBQWMsR0FpYXhEO0FBamFZLHNEQUFxQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog56CU56m26Zi/6YeM5LqR55qET1RT6KGo5qC86K6+6K6h5bCGc2Vzc2lvbuOAgWNhY2hl44CBdXNlcuS4ieenjee8k+WtmOS/oeaBr+eul+azleaehOW7uuWcqOatpOS5i+S4iuOAglxuICovXG5jb25zdCBUYWJsZVN0b3JlID0gcmVxdWlyZSgndGFibGVzdG9yZScpXG5jb25zdCBMb25nID0gVGFibGVTdG9yZS5Mb25nXG5jb25zdCBfID0gcmVxdWlyZSgnbG9kYXNoJylcblxuYWJzdHJhY3QgY2xhc3MgTm9TcWxJbnRlcmZhY2Uge1xuICAgIGNvbnN0cnVjdG9yKHRhYmxlOiBzdHJpbmcsIGNvbmZpZzogc3RyaW5nIHwge31bXSA9ICdkZWZhdWx0Jykge1xuICAgIH1cblxuICAgIC8vIOe6puWumuaJgOacieihqOmDvemcgOimgeacieiHquWinuS4u+mUrmlk5L2c5Li65YaF6YOo5ZSv5LiA5qCH6K+G56CB77yM5YW25L2Z5LiJ5Liq5Li76ZSu5b+F6aG75YWo6YOo5Li65a2X56ym5Liy44CC77yI5ZCO56uv6ZyA6KaB5omp5bGVaW505ZKMZGF0ZeWfuuacrOaVsOaNruexu+Wei+S7peWPiuaTjeS9nOespumHjei9veWunueOsOS8mOWMluW8gOWPke+8iVxuICAgIC8vIOWxnuaAp+Wtl+auteWPr+S7peagueaNruS4muWKoea8lOWPmOS7u+aEj+eahOaJqeWxleWinuWKoOeUseS4muWKoeS7o+eggeWvueS6juiAgeaVsOaNruS4jeWtmOWcqOaWsOWinuWtl+auteWAvOeahOaDheWGteWBmuWFvOWuueWkhOeQhlxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBpbnNlcnQoaWQsIGt2dDogeyBbaW5kZXg6IHN0cmluZ106IHN0cmluZyB8IHsgdmFsdWU6IHN0cmluZywgdGltZXN0YW1wOiBudW1iZXIgfSB9KSA7XG5cbiAgICAvLyDmnaHku7bmm7TmlrDlv4XpobvopoHloavlhpnkuLvplK7orrDlvZXlgLwo5LuF5LuF5YWB6K645pu05paw5bGe5oCn5a2X5q616ICM5Li76ZSu5a2X5q615piv5LiN5YWB6K645pu05paw55qE77yMXG4gICAgLy8gICAgICDmlbTliJfmm7TmlrDlkozliKDpmaTliJflsZ7kuo7ov5Dnu7Tmk43kvZznpoHmraLlupTnlKjkuK3kvb/nlKjpnIDopoHljZXni6zmjqXlj6Pku6Xlj4rmnYPpmZDorqTor4EpXG4gICAgcHVibGljIGFic3RyYWN0IGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBrdnQ6IHsgW2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsIHwgbnVtYmVyIH0pIDtcblxuICAgIC8vIOS7peS4u+mUruS9nOS4uuadoeS7tuWIoOmZpOiusOW9leWAvFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyk7XG5cbiAgICAvLyDliIbpobXmn6Xor6LkuIDmrKHmo4DntKJO5p2h6K6w5b2VXG4gICAgcHVibGljIGFic3RyYWN0IGFzeW5jIHF1ZXJ5KGlkOiBzdHJpbmcsIGtleXM6IHN0cmluZ1tdIHwgbnVsbCwgbWF4X3ZlcnNpb246IG51bWJlcik6IFByb21pc2U8YW55PjtcblxuICAgIC8vIOmUgOavgeihqFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBkZXN0cm95KCk7XG5cbiAgICAvLyDliJvlu7rooahcbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgY3JlYXRlKCk7XG5cbiAgICAvLyDmn6Xor6LlvZPliY3ooajnmoTmj4/ov7Dkv6Hmga9cbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgZGVzY3JpYmUoKTtcblxuICAgIC8vIOWPmOabtOihqFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBjaGFuZ2UocGFyYW06IHtcbiAgICAgICAgbWF4VmVyc2lvbnM/OiBudW1iZXIsIHRpbWVvdXRTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dFJlYWQ/OiBudW1iZXIsIHJlc2VydmVkVGhyb3VnaHB1dFdyaXRlPzogbnVtYmVyXG4gICAgfSk7XG5cbiAgICAvLyDph43nva7ooahcbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgcmVzZXQoKTtcbn1cblxuLy8gZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3QoKSB7XG4vLyAgICAgY29uc3Qgb3RzID0gbmV3IE5vU3FsQWxpeXVuVGFibGVzdG9yZSgnc2Vzc2lvbl90ZXN0MycpXG4vLyAgICAgLy8gbGV0IG91dCA9IGF3YWl0IG90cy5jcmVhdGUoNjApXG4vLyAgICAgLy8gRklYTUUg6aaW5qyh5Yib5bu66KGo6ZyA6KaB5pyJ5LiA5a6a55qE57O757uf5bu26L+f5pe26Ze077yM6ZyA6KaB5pS+5YiwaW5zdGFsbOi/h+eoi+S4rei/m+ihjOe7tOaKpOOAglxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMuaW5zZXJ0KCd4Jywge2E6ICdhYWEnLCBiOiB7dmFsdWU6ICdiYmJiJywgdGltZXN0YW1wOiBEYXRlLm5vdygpfX0pXG4vLyAgICAgLy8gbGV0IG91dCA9IGF3YWl0IG90cy51cGRhdGUoJ3gnLCB7YTogJ2FhYTInLCBiOiAnYmJiMid9KVxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMudXBkYXRlKCd4Jywge2E6IG51bGwsIGI6IDE1Mjk2NjYwNTMxMDB9KVxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMuZGVsZXRlKCd4Jylcbi8vXG4vLyAgICAgbGV0IG91dFxuLy8gICAgIC8vIG91dCA9IGF3YWl0IG90cy5pbnNlcnQoJ3gnLCB7YTogJ2FhYScsIGI6IHt2YWx1ZTogJ2JiYmInLCB0aW1lc3RhbXA6IERhdGUubm93KCl9fSlcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3gnKSAgLy8g5Y+W5YWo6YOo55qE5a2X5q61XG4vLyAgICAgLy8gb3V0ID0gYXdhaXQgb3RzLnF1ZXJ5KCd4JywgWydhJ10pICAvLyDlj5bpg6jliIblrZfmrrVcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3knKSAgLy8g5Y+W5LiN5a2Y5Zyo55qE5Li76ZSuXG4vL1xuLy8gICAgIC8vIG91dCA9IGF3YWl0IG90cy5jcmVhdGUoMjQqNjAqNjAsMilcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMuaW5zZXJ0KCd6Jywge2E6ICdhYWEnK0RhdGUoKSwgYjoge3ZhbHVlOiAnYmJiYicrRGF0ZSgpLCB0aW1lc3RhbXA6IERhdGUubm93KCl9fSlcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMudXBkYXRlKCd6Jywge2E6ICdhYWEnK0RhdGUoKSwgYjogJ2JiYmInK0RhdGUoKX0pXG4vLyAgICAgLy8gb3V0ID0gYXdhaXQgb3RzLnF1ZXJ5KCd6JywgbnVsbCwgMilcbi8vICAgICBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3onLCBudWxsLCAxKVxuLy8gICAgIC8vIOeUqOacgOS9s+aWueahiOWOu+WunueOsOWtl+autVxuLy8gICAgIHJldHVybiBvdXRcbi8vIH1cblxuLy8g5a+55LqO6Zi/6YeM5LqRdGFibGVzdG9yZeeahOWNleihqOWKn+iDveeugOWNleWwgeijheWkhOeQhu+8iOS4gOS4quS4u+mUruW5tuS9nOS4uuWIhuWMuuWUr+S4gOWMuuWIhuS4gOS4quiusOW9le+8jOS7heeUqOS6jue8k+WtmOWKn+iDveWunueOsOOAglxuLy8g5bCB6KOF54m554K577ya5q+P5Liq6K6w5b2V5LiA5p2h5Li76ZSu5bm25L2c5Li65YiG5Yy677yM5q+P5Liq6K6w5b2V5pyJ5peg5pWw5Liqa3blgLzlj6/kvpvphY3nva7vvIzmr4/kuKprduWAvOmDveacieS4gOS4quaXtumXtOaIs+i2heaXtuaXtumXtOWcqOihqOS4iuWNleeLrOmFjee9ruOAgu+8iVxuZXhwb3J0IGNsYXNzIE5vU3FsQWxpeXVuVGFibGVzdG9yZSBleHRlbmRzIE5vU3FsSW50ZXJmYWNlIHtcbiAgICBwcml2YXRlIF90YWJsZTogc3RyaW5nXG4gICAgcHJpdmF0ZSBfY2xpZW50OiBhbnlcbiAgICBwcml2YXRlIF9zY2hlbWE6IGFueVxuXG4gICAgc2V0IHRhYmxlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3RhYmxlID0gdmFsdWVcbiAgICB9XG5cbiAgICBjb25zdHJ1Y3Rvcih0YWJsZTogc3RyaW5nLCBjb25maWc6IHN0cmluZyA9ICdkZWZhdWx0Jykge1xuICAgICAgICBzdXBlcih0YWJsZSwgY29uZmlnKVxuICAgICAgICBjb25zdCBpbnN0YW5jZXMgPSB4Y29uZmlnKCdwbHVnaW5zLm5vc3FsJylcbiAgICAgICAgeGFzc2VydChpbnN0YW5jZXMgJiYgXy5pc1BsYWluT2JqZWN0KGluc3RhbmNlcykgJiYgY29uZmlnIGluIGluc3RhbmNlcyxcbiAgICAgICAgICAgIEVSUiRDT05GSUcsIHtpbnN0YW5jZXN9KVxuICAgICAgICB0aGlzLl90YWJsZSA9IHRhYmxlXG4gICAgICAgIHRoaXMuX3NjaGVtYSA9IHtcbiAgICAgICAgICAgIEtFWVM6IHtcbiAgICAgICAgICAgICAgICBpZDogJ3N0cmluZycgLy8g6KGo55qE5ZSv5LiA6K6w5b2V5Li76ZSu5YC85ZCM5pe25Lmf5piv5YiG5Yy6XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jbGllbnQgPSBuZXcgVGFibGVTdG9yZS5DbGllbnQoe1xuICAgICAgICAgICAgYWNjZXNzS2V5SWQ6IGluc3RhbmNlc1tjb25maWddLk9UU19BQ0NFU1NfS0VZX0lELFxuICAgICAgICAgICAgc2VjcmV0QWNjZXNzS2V5OiBpbnN0YW5jZXNbY29uZmlnXS5PVFNfU0VDUkVURV9BQ0NFU1NfS0VZLFxuICAgICAgICAgICAgZW5kcG9pbnQ6IGluc3RhbmNlc1tjb25maWddLk9UU19FTkRQT0lOVCxcbiAgICAgICAgICAgIGluc3RhbmNlbmFtZTogaW5zdGFuY2VzW2NvbmZpZ10uT1RTX0lOU1RBTkNFTkFNRVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOe6puWumuaJgOacieihqOmDvemcgOimgeacieiHquWinuS4u+mUrmlk5L2c5Li65YaF6YOo5ZSv5LiA5qCH6K+G56CB77yM5YW25L2Z5LiJ5Liq5Li76ZSu5b+F6aG75YWo6YOo5Li65a2X56ym5Liy44CC77yI5ZCO56uv6ZyA6KaB5omp5bGVaW505ZKMZGF0ZeWfuuacrOaVsOaNruexu+Wei+S7peWPiuaTjeS9nOespumHjei9veWunueOsOS8mOWMluW8gOWPke+8iVxuICAgIC8vIOWxnuaAp+Wtl+auteWPr+S7peagueaNruS4muWKoea8lOWPmOS7u+aEj+eahOaJqeWxleWinuWKoOeUseS4muWKoeS7o+eggeWvueS6juiAgeaVsOaNruS4jeWtmOWcqOaWsOWinuWtl+auteWAvOeahOaDheWGteWBmuWFvOWuueWkhOeQhlxuICAgIHB1YmxpYyBhc3luYyBpbnNlcnQoaWQ6IHN0cmluZywga3Z0OiB7IFtpbmRleDogc3RyaW5nXTogc3RyaW5nIHwgeyB2YWx1ZTogc3RyaW5nLCB0aW1lc3RhbXA6IG51bWJlciB9IH0pIHtcbiAgICAgICAgeGFzc2VydChPYmplY3Qua2V5cyhrdnQpLmxlbmd0aCA8PSAxMjgpIC8vIOinhOmBv+i3qOihjOmZkOWItuaAu+iuoeWxnuaApzEyOOS4qlxuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgLy8gdmFyIGN1cnJlbnRUaW1lU3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgLy8g5o+S5YWl55qE5pe25YCZ6ZyA6KaB56Gu5L+d5LiN5a2Y5Zyo5a+55bqU55qE5pWw5o2u5Lul6Ziy5q2i5Ye66ZSZXG4gICAgICAgICAgICBjb25kaXRpb246IG5ldyBUYWJsZVN0b3JlLkNvbmRpdGlvbihUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLkVYUEVDVF9OT1RfRVhJU1QsIG51bGwpLFxuICAgICAgICAgICAgcHJpbWFyeUtleTogW10sXG4gICAgICAgICAgICBhdHRyaWJ1dGVDb2x1bW5zOiBbXSxcbiAgICAgICAgICAgIC8vIOaMieeFp+S4i+mdouaVsOaNruagvOW8j+i/m+ihjHNjaGVtYeWumuS5ieeahOmqjOivgeS7peWPiuaVsOaNruexu+Wei+i9rOaNolxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW3snZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX0sIHsndWlkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX1dLFxuICAgICAgICAgICAgLy8gYXR0cmlidXRlQ29sdW1uczogW1xuICAgICAgICAgICAgLy8gICAgIHsnY29sMSc6ICfooajmoLzlrZjlgqgnfSxcbiAgICAgICAgICAgIC8vICAgICB7J2NvbDInOiAnMicsICd0aW1lc3RhbXAnOiBjdXJyZW50VGltZVN0YW1wfSwgLy8g5YWB6K645L+u5pS55pe26Ze05oiz5LmQ6KeC6ZSB5Yqf6IO95a6e546w5pqC5LiN5pSv5oyBXG4gICAgICAgICAgICAvLyAgICAgeydjb2wzJzogMy4xfSxcbiAgICAgICAgICAgIC8vICAgICB7J2NvbDQnOiAtMC4zMn0sXG4gICAgICAgICAgICAvLyAgICAgeydjb2w1JzogTG9uZy5mcm9tTnVtYmVyKDEyMzQ1Njc4OSl9XG4gICAgICAgICAgICAvLyBdLFxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW1xuICAgICAgICAgICAgLy8gICAgIHsnc2hvcnRfaWQnOiAncGsxJ30sXG4gICAgICAgICAgICAvLyAgICAge1tBVVRPX0tFWV9OQU1FXTogVGFibGVTdG9yZS5QS19BVVRPX0lOQ1J9XG4gICAgICAgICAgICAvLyBdLFxuICAgICAgICAgICAgLy8gYXR0cmlidXRlQ29sdW1uczogW1xuICAgICAgICAgICAgLy8gICAgIHsnYXBwY29kZSc6ICdhcHAxJ31cbiAgICAgICAgICAgIC8vIF0sXG4gICAgICAgICAgICByZXR1cm5Db250ZW50OiB7cmV0dXJuVHlwZTogVGFibGVTdG9yZS5SZXR1cm5UeXBlLlByaW1hcnlrZXl9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDmi7zmjqXkuLvplK7ku6Xlj4rlsZ7mgKflrZfmrrXlgLxcbiAgICAgICAgcGFyYW1zLnByaW1hcnlLZXkgPSBbeydpZCc6IGlkfV1cbiAgICAgICAgZm9yIChsZXQgayBpbiBrdnQpIHtcbiAgICAgICAgICAgIHhhc3NlcnQoayAhPSAnaWQnICYmIGsgIT0gJ3RpbWVzdGFtcCcpIC8vIOS4pOS4qumihOeVmeWGhemDqOagh+ivhuespuS4jeWPr+S9nOS4uuWxnuaAp+WQjVxuICAgICAgICAgICAgaWYgKF8uaXNTdHJpbmcoa3Z0W2tdKSkge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5hdHRyaWJ1dGVDb2x1bW5zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBba106IGt2dFtrXVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5hdHRyaWJ1dGVDb2x1bW5zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBba106IGt2dFtrXVsndmFsdWUnXSxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBrdnRba11bJ3RpbWVzdGFtcCddXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIF9fdGhpc19fLl9jbGllbnQucHV0Um93KHBhcmFtcywgZnVuY3Rpb24gKGVyciwgb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBvdXR9KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8g5q2j5bi46L+U5Zue55qE5pWw5o2u5qC85byPXG4gICAgICAgICAgICAgICAgICAgIC8ve1wiY29uc3VtZWRcIjp7XCJjYXBhY2l0eV91bml0XCI6e1wicmVhZFwiOjAsXCJ3cml0ZVwiOjF9fSxcInJvd1wiOntcbiAgICAgICAgICAgICAgICAgICAgLy8gIFwicHJpbWFyeUtleVwiOlt7XCJuYW1lXCI6XCJzaG9ydF9pZFwiLFwidmFsdWVcIjpcImFiY2RcIn0se1wibmFtZVwiOlwiaWRcIixcInZhbHVlXCI6MTUyMDc2NTUwMjM0NzAwMH1dLFxuICAgICAgICAgICAgICAgICAgICAvLyAgXCJhdHRyaWJ1dGVzXCI6W119LFxuICAgICAgICAgICAgICAgICAgICAvLyBcIlJlcXVlc3RJZFwiOlwiMDAwNTY3MjAtY2Y4ZC1kNGE4LThhZTgtOTcwYTE3ODk0Y2U2XCJ9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUob3V0KVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBrdnQ6IHsgW2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsIHwgbnVtYmVyIH0pIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX3VwZGF0ZV9vcl9yZXBsYWNlKGlkLCBrdnQsIGZhbHNlKVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXBsYWNlKGlkOiBzdHJpbmcsIGt2dDogeyBbaW5kZXg6IHN0cmluZ106IHN0cmluZyB8IG51bGwgfCBudW1iZXIgfSkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fdXBkYXRlX29yX3JlcGxhY2UoaWQsIGt2dCwgdHJ1ZSlcbiAgICB9XG5cbiAgICAvLyDmnaHku7bmm7TmlrDlv4XpobvopoHloavlhpnkuLvplK7orrDlvZXlgLwo5LuF5LuF5YWB6K645pu05paw5bGe5oCn5a2X5q616ICM5Li76ZSu5a2X5q615piv5LiN5YWB6K645pu05paw55qE77yMXG4gICAgLy8gICAgICDmlbTliJfmm7TmlrDlkozliKDpmaTliJflsZ7kuo7ov5Dnu7Tmk43kvZznpoHmraLlupTnlKjkuK3kvb/nlKjpnIDopoHljZXni6zmjqXlj6Pku6Xlj4rmnYPpmZDorqTor4EpXG4gICAgcHJpdmF0ZSBhc3luYyBfdXBkYXRlX29yX3JlcGxhY2UoaWQ6IHN0cmluZywga3Z0OiB7IFtpbmRleDogc3RyaW5nXTogc3RyaW5nIHwgbnVsbCB8IG51bWJlciB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzSWdub3JlUm93Tm9uRXhpc3Q6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgICAgICB4YXNzZXJ0KE9iamVjdC5rZXlzKGt2dCkubGVuZ3RoID4gMCAmJiBPYmplY3Qua2V5cyhrdnQpLmxlbmd0aCA8PSAxMjgpIC8vIOinhOmBv+i3qOihjOmZkOWItuaAu+iuoeWxnuaApzEyOOS4qlxuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZSxcbiAgICAgICAgICAgIGNvbmRpdGlvbjogbmV3IFRhYmxlU3RvcmUuQ29uZGl0aW9uKGlzSWdub3JlUm93Tm9uRXhpc3QgP1xuICAgICAgICAgICAgICAgIFRhYmxlU3RvcmUuUm93RXhpc3RlbmNlRXhwZWN0YXRpb24uSUdOT1JFIDpcbiAgICAgICAgICAgICAgICBUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLkVYUEVDVF9FWElTVCwgbnVsbCksXG4gICAgICAgICAgICBwcmltYXJ5S2V5OiBbe2lkfV0sXG4gICAgICAgICAgICAvLyB1cGRhdGVPZkF0dHJpYnV0ZUNvbHVtbnM6IFt7J1BVVCc6IFt7J2NvbDEnOiAndGVzdDYnfV19XVxuICAgICAgICAgICAgdXBkYXRlT2ZBdHRyaWJ1dGVDb2x1bW5zOiBbXVxuICAgICAgICAgICAgLy8gdXBkYXRlT2ZBdHRyaWJ1dGVDb2x1bW5zOiBbXG4gICAgICAgICAgICAvLyAgICAgeyAnUFVUJzogW3sgJ2NvbDQnOiBMb25nLmZyb21OdW1iZXIoNCkgfSwgeyAnY29sNSc6ICc1JyB9LCB7ICdjb2w2JzogTG9uZy5mcm9tTnVtYmVyKDYpIH1dIH0sXG4gICAgICAgICAgICAvLyAgICAgeyAnREVMRVRFJzogW3sgJ2NvbDEnOiBMb25nLmZyb21OdW1iZXIoMTQ5NjgyNjQ3MzE4NikgfV0gfSwgLy8g5Yig6Zmk5oyH5a6a5pe26Ze05oiz54mI5pys5pWw5o2uXG4gICAgICAgICAgICAvLyAgICAgeyAnREVMRVRFX0FMTCc6IFsnY29sMiddIH0gLy8g5Yig6Zmk5omA5pyJ54mI5pys55qE5a2X5q615pWw5o2uXG4gICAgICAgICAgICAvLyBdXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBQVVQgPSBbXVxuICAgICAgICBjb25zdCBERUxFVEUgPSBbXVxuICAgICAgICBjb25zdCBERUxFVEVfQUxMID0gW11cbiAgICAgICAgZm9yIChsZXQgayBpbiBrdnQpIHtcbiAgICAgICAgICAgIC8vIOWmguaenOWPmOmHj+WAvOS4um51bGznsbvlnovliJnooajnpLrliKDpmaTlr7nlupTnmoTlrZfmrrXlgLzvvIzlpoLmnpzkuLrmlbTmlbDooajnpLrliKDpmaTmjIflrprml7bpl7TmiLPniYjmnKzvvIzlkKbliJnooajnpLrmt7vliqDmiJbmm7TmlrDlr7nlupTlrZfmrrXlgLzjgIJcbiAgICAgICAgICAgIGlmICgha3Z0W2tdKSB7XG4gICAgICAgICAgICAgICAgREVMRVRFX0FMTC5wdXNoKGspXG4gICAgICAgICAgICB9IGVsc2UgaWYgKF8uaXNJbnRlZ2VyKGt2dFtrXSkpIHtcbiAgICAgICAgICAgICAgICBERUxFVEUucHVzaCh7W2tdOiBMb25nLmZyb21OdW1iZXIoa3Z0W2tdKX0pXG4gICAgICAgICAgICB9IGVsc2UgaWYgKF8uaXNTdHJpbmcoa3Z0W2tdKSkge1xuICAgICAgICAgICAgICAgIFBVVC5wdXNoKHtba106IGt2dFtrXX0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHhhc3NlcnQoZmFsc2UsIEVSUiRQQVJBTSwge2lkLCBrdnR9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChQVVQubGVuZ3RoID4gMCkgcGFyYW1zLnVwZGF0ZU9mQXR0cmlidXRlQ29sdW1ucy5wdXNoKHtQVVR9KVxuICAgICAgICBpZiAoREVMRVRFLmxlbmd0aCA+IDApIHBhcmFtcy51cGRhdGVPZkF0dHJpYnV0ZUNvbHVtbnMucHVzaCh7REVMRVRFfSlcbiAgICAgICAgaWYgKERFTEVURV9BTEwubGVuZ3RoID4gMCkgcGFyYW1zLnVwZGF0ZU9mQXR0cmlidXRlQ29sdW1ucy5wdXNoKHtERUxFVEVfQUxMfSlcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBfX3RoaXNfXy5fY2xpZW50LnVwZGF0ZVJvdyhwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHh0aHJvdyhlcnIsIHJlamVjdClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyDku6XkuLvplK7kvZzkuLrmnaHku7bliKDpmaTorrDlvZXlgLxcbiAgICBwdWJsaWMgYXN5bmMgZGVsZXRlKGlkOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgX190aGlzX18gPSB0aGlzXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHRhYmxlTmFtZTogdGhpcy5fdGFibGUsXG4gICAgICAgICAgICBjb25kaXRpb246IG5ldyBUYWJsZVN0b3JlLkNvbmRpdGlvbihUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLklHTk9SRSwgbnVsbCksXG4gICAgICAgICAgICAvLyBwcmltYXJ5S2V5OiBbeyAnZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDgpIH0sIHsgJ3VpZCc6IExvbmcuZnJvbU51bWJlcig4MCkgfV1cbiAgICAgICAgICAgIHByaW1hcnlLZXk6IFt7aWR9XVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5kZWxldGVSb3cocGFyYW1zLCBmdW5jdGlvbiAoZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBkYXRhfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8g6IyD5Zu05p+l6K+i6ZyA6KaB5pWw5o2u6Ieq5Yqo5ZCM5q2l5Yiwb3BlbnNlYXJjaOi/m+ihjOe0ouW8leWQjOatpeWQjui/m+ihjOWQhOenjeWkjeadgueahOafpeivouaTjeS9nOWunueOsOWFjei/kOe7tOezu+e7n+eahOWunueOsFxuICAgIC8vIOWNleihqOmAu+i+keadoeS7tueahOeugOWNlWFuZOS4jmVxdWFs55qE5p+l6K+i77yM6L+U5Zue5ruh6Laz5p2h5Lu255qE56ys5LiA5p2h6K6w5b2VIO+8iOWQiOW5tuS4uuS4gOS4quafpeivouWFvOWuuW1vbmdvZGLnmoTmn6Xor6LmianlsZXvvIlcbiAgICBwdWJsaWMgYXN5bmMgcXVlcnkoaWQ6IHN0cmluZywga2V5czogc3RyaW5nW10gfCBudWxsID0gbnVsbCwgbWF4X3ZlcnNpb246IG51bWJlciA9IDEpOiBQcm9taXNlPGFueT4ge1xuXG4gICAgICAgIGNvbnN0IF9fdGhpc19fID0gdGhpc1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgY29sdW1uc1RvR2V0OiBrZXlzLFxuICAgICAgICAgICAgLy8gY29sdW1uc190b19nZXQg6I635Y+W5pyf5pyb55qE5YiX5pyA5aSaMTI45Liq5LiA5qyh6I635Y+W5oC75pWw77yM5bqU55So5LiK5bqU6K+l5bCGS0VZ6KeG5Li65YiG57uE5oC75pWw44CCXG4gICAgICAgICAgICAvLyDlpoLkvZXop4Tpgb/lrr3ooajnmoTliIbpobXpmZDliLbvvJ/vvJ8gRklYTUUg5YWI5LuO5bqU55So5LiK6KeE6YG/6ZmQ5Yi25LiA5Liq5bqU55So5pyA5aSa5LiN6LaF6L+HMTI45Liq5bGe5oCn77yM6YCa6L+HSlNPTui/m+ihjOaJqeWxleWtmOWCqOOAglxuICAgICAgICAgICAgcHJpbWFyeUtleTogW3tpZH1dLFxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW3snZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX0sIHsndWlkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX1dLFxuICAgICAgICAgICAgY29sdW1uRmlsdGVyOiBudWxsLFxuICAgICAgICAgICAgbWF4VmVyc2lvbnM6IG1heF92ZXJzaW9uLFxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIF9fdGhpc19fLl9jbGllbnQuZ2V0Um93KHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyDov5Tlm57mlbDmja7moLzlvI/nsbvlnovov5vooYzovazmjaLlpITnkIZcbiAgICAgICAgICAgICAgICAvLyB7XCJjb25zdW1lZFwiOntcImNhcGFjaXR5X3VuaXRcIjp7XCJyZWFkXCI6MSxcIndyaXRlXCI6MH19LFxuICAgICAgICAgICAgICAgIC8vICBcInJvd1wiOntcInByaW1hcnlLZXlcIjpbe1wibmFtZVwiOlwiZ2lkXCIsXCJ2YWx1ZVwiOjIwMDEzfSx7XCJuYW1lXCI6XCJ1aWRcIixcInZhbHVlXCI6MjAwMTN9XSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICBcImF0dHJpYnV0ZXNcIjpbe1wiY29sdW1uTmFtZVwiOlwiY29sMVwiLFwiY29sdW1uVmFsdWVcIjpcIuihqOagvOWtmOWCqFwiLFwidGltZXN0YW1wXCI6MTUyMDczNDUyMDI4Nn0sXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAge1wiY29sdW1uTmFtZVwiOlwiY29sMlwiLFwiY29sdW1uVmFsdWVcIjpcIjJcIixcInRpbWVzdGFtcFwiOjE1MjA3MzQ1MjAwNjR9LFxuICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAge1wiY29sdW1uTmFtZVwiOlwiY29sM1wiLFwiY29sdW1uVmFsdWVcIjozLjEsXCJ0aW1lc3RhbXBcIjoxNTIwNzM0NTIwMjg2fSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgIHtcImNvbHVtbk5hbWVcIjpcImNvbDRcIixcImNvbHVtblZhbHVlXCI6LTAuMzIsXCJ0aW1lc3RhbXBcIjoxNTIwNzM0NTIwMjg2fSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgIHtcImNvbHVtbk5hbWVcIjpcImNvbDVcIixcImNvbHVtblZhbHVlXCI6MTIzNDU2Nzg5LFwidGltZXN0YW1wXCI6MTUyMDczNDUyMDI4Nn1dXG4gICAgICAgICAgICAgICAgLy8gICAgICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gXCJuZXh0X3Rva2VuXCI6bnVsbCxcIlJlcXVlc3RJZFwiOlwiMDAwNTY3MTktZTJhZC03M2IxLWRiZDgtOTcwYTE5NTIyZjRiXCJ9XG5cbiAgICAgICAgICAgICAgICAvLyDlsIbmlbDmja7nu5Pmnpzov5vooYzovazmjaLlpITnkIblkIjlubbkuLrkuIDkuKrmma7pgJrlr7nosaHnu5nlupTnlKjkvb/nlKhcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3V0OiBhbnkgPSB7fVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEucm93KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJvdy5wcmltYXJ5S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrIGluIGRhdGEucm93LnByaW1hcnlLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRbZGF0YS5yb3cucHJpbWFyeUtleVtrXS5uYW1lXSA9IGRhdGEucm93LnByaW1hcnlLZXlba10udmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5yb3cuYXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayBpbiBkYXRhLnJvdy5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0W2RhdGEucm93LmF0dHJpYnV0ZXNba10uY29sdW1uTmFtZV0gPSBkYXRhLnJvdy5hdHRyaWJ1dGVzW2tdLmNvbHVtblZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8geGxvZyhkYXRhKSAvLyBUT0RPIOW9k+WtmOWcqOWkmuS4queJiOacrOaVsOaNrueahOaXtuWAmeino+aekOS4jeato+ehru+8jOW6lOivpeaYr+WkmuS4queJiOacrOeahOWxnuaAp+WAvOWtl+auteeahOe7hOWQiOaJjeato+ehruOAglxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKF8uaXNFbXB0eShvdXQpID8gbnVsbCA6IG91dClcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOmUgOavgeihqFxuICAgIHB1YmxpYyBhc3luYyBkZXN0cm95KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZGVzdHJveSgpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgLy8gMTDnp5Lpkp/nrYnlvoXotoXml7bplIDmr4HooajmraPluLjlrozmiJBcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDA7IGkrKykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgb3V0ID0gdGhpcy5kZXNjcmliZSgpXG4gICAgICAgICAgICAgICAgeGxvZyhvdXQpXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB4c2xlZXAoMTAwKVxuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9kZXN0cm95KCkge1xuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBfX3RoaXNfXy5fY2xpZW50LmRlbGV0ZVRhYmxlKHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXN9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOWIm+W7uuihqFxuICAgIHB1YmxpYyBhc3luYyBjcmVhdGUodGltZW91dCA9IC0xLCBtYXhfdmVyc2lvbnMgPSAxKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2NyZWF0ZSh0aW1lb3V0LCBtYXhfdmVyc2lvbnMpXG4gICAgICAgIC8vIDEw56eS6ZKf562J5b6F6LaF5pe25Yib5bu66KGo5q2j5bi45a6M5oiQXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTAwOyBpKyspIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IG91dCA9IHRoaXMuZGVzY3JpYmUoKVxuICAgICAgICAgICAgICAgIHhsb2cob3V0KVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgeHNsZWVwKDEwMClcbiAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2NyZWF0ZSh0aW1lb3V0ID0gLTEsIG1heF92ZXJzaW9ucyA9IDEpIHtcbiAgICAgICAgLy8gT1RT5pyA6ZW/6LaF5pe25pe26Ze05Li6MeWkqeeahOWFvOWuueWkhOeQhlxuICAgICAgICBpZiAodGltZW91dCAhPSAtMSAmJiB0aW1lb3V0IDwgODY0MDApIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSA4NjQwMFxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IF9fdGhpc19fID0gdGhpc1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU1ldGE6IHtcbiAgICAgICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgICAgIHByaW1hcnlLZXk6IFtdIGFzIGFueVtdLFxuICAgICAgICAgICAgICAgIC8vIHByaW1hcnlLZXk6IFtcbiAgICAgICAgICAgICAgICAvLyAgICAge1xuICAgICAgICAgICAgICAgIC8vICAgICAgICAgbmFtZTogJ3Nob3J0X2lkJyxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgIHR5cGU6ICdTVFJJTkcnXG4gICAgICAgICAgICAgICAgLy8gICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gICAgIHtcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgIG5hbWU6IEFVVE9fS0VZX05BTUUsXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICB0eXBlOiAnSU5URUdFUicsXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICBvcHRpb246ICdBVVRPX0lOQ1JFTUVOVCcsXG4gICAgICAgICAgICAgICAgLy8gICAgIH1cbiAgICAgICAgICAgICAgICAvLyBdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzZXJ2ZWRUaHJvdWdocHV0OiB7XG4gICAgICAgICAgICAgICAgY2FwYWNpdHlVbml0OiB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWQ6IDAsXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlOiAwXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRhYmxlT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHRpbWVUb0xpdmU6IHRpbWVvdXQsLy8g5pWw5o2u55qE6L+H5pyf5pe26Ze0LCDljZXkvY3np5IsIC0x5Luj6KGo5rC45LiN6L+H5pyfLiDlgYflpoLorr7nva7ov4fmnJ/ml7bpl7TkuLrkuIDlubQsIOWNs+S4uiAzNjUgKiAyNCAqIDM2MDAuXG4gICAgICAgICAgICAgICAgbWF4VmVyc2lvbnM6IG1heF92ZXJzaW9ucywvLyDkv53lrZjnmoTmnIDlpKfniYjmnKzmlbAsIOiuvue9ruS4ujHljbPku6Pooajmr4/liJfkuIrmnIDlpJrkv53lrZjkuIDkuKrniYjmnKwo5L+d5a2Y5pyA5paw55qE54mI5pysKS5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyDoh6rliqjovazmjaJzY2hlbWHlrprkuYnkuLpPVFPnmoTmlbDmja7nu5PmnoRcbiAgICAgICAgZm9yIChsZXQgayBpbiB0aGlzLl9zY2hlbWEuS0VZUykge1xuICAgICAgICAgICAgbGV0IG9iaiA9IHtcbiAgICAgICAgICAgICAgICBuYW1lOiBrLFxuICAgICAgICAgICAgICAgIHR5cGU6IF8udXBwZXJDYXNlKHRoaXMuX3NjaGVtYS5LRVlTW2tdKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgKGsgPT0gQVVUT19LRVlfTkFNRSkge1xuICAgICAgICAgICAgLy8gICAgIG9ialsnb3B0aW9uJ10gPSAnQVVUT19JTkNSRU1FTlQnXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICBwYXJhbXMudGFibGVNZXRhLnByaW1hcnlLZXkucHVzaChvYmopXG4gICAgICAgIH1cbiAgICAgICAgLy8gYnVnZml46Kej5Yaz56ys5LiA5Liq5YiG5Yy66ZSu5LiN6IO95Li66Ieq5aKe5Li76ZSu55qE6Zeu6aKY6buY6K6k6KGl5LiK5LiA5LiqX2lk5a2X5q615YC855qE6Zeu6aKY77yI5Y+q5YGa5o+Q56S65pqC5LiN6Kej5Yaz57qm5a6a5LiA5LiqX2lk5YiG5Yy66ZSu5by65Yi26K6+572u77yJXG4gICAgICAgIC8vIFwiNDAwOiBcXG5cXHUwMDEzT1RTUGFyYW1ldGVySW52YWxpZFxcdTAwMTIqZmlyc3QgcHJpbWFyeSBrZXkgY2FuJ3QgYmUgQVVUT19JTkNSRU1FTlQuXCJcblxuICAgICAgICBsZXQgb3V0ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5jcmVhdGVUYWJsZShwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBkYXRhfSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcblxuICAgICAgICAvLyBGSVhNRSDooajliJvlu7rlkI7mnInkuIDlrprnmoTlu7bml7bml7bpl7TmiY3og73nlJ/mlYjvvIzpnIDopoHnu7TmjIHkuIDlrprnmoTnrYnlvoXml7bpl7Tnoa7kv53mraPluLjmiafooYzlrozmiJDjgIJcbiAgICAgICAgLy8gVE9ETyDlu7bml7bnrpfms5Xoh6rliqjlrozmiJDml7bpl7TmiLPnmoTlpITnkIbjgIJcbiAgICAgICAgcmV0dXJuIG91dFxuICAgIH1cblxuICAgIC8vIOafpeivouW9k+WJjeihqOeahOaPj+i/sOS/oeaBr1xuICAgIHB1YmxpYyBhc3luYyBkZXNjcmliZSgpIHtcbiAgICAgICAgY29uc3QgX190aGlzX18gPSB0aGlzXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHRhYmxlTmFtZTogdGhpcy5fdGFibGVcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5kZXNjcmliZVRhYmxlKHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXN9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyDooajphY3nva7kv6Hmga/nmoTmm7TmlrDlpITnkIYo5pe26Ze05oiz5Lul5Y+K54mI5pys5Y+3KVxuICAgIHB1YmxpYyBhc3luYyBjaGFuZ2UocGFyYW06IHtcbiAgICAgICAgbWF4VmVyc2lvbnM/OiBudW1iZXIsIHRpbWVvdXRTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dFJlYWQ/OiBudW1iZXIsIHJlc2VydmVkVGhyb3VnaHB1dFdyaXRlPzogbnVtYmVyXG4gICAgfSkge1xuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZSxcbiAgICAgICAgICAgIHRhYmxlT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIC8vIOS/neWtmOeahOacgOWkp+eJiOacrOaVsCwg6K6+572u5Li6MeWNs+S7o+ihqOavj+WIl+S4iuacgOWkmuS/neWtmOS4gOS4queJiOacrCjkv53lrZjmnIDmlrDnmoTniYjmnKwpLlxuICAgICAgICAgICAgICAgIG1heFZlcnNpb25zOiBwYXJhbS5tYXhWZXJzaW9ucyA/IHBhcmFtLm1heFZlcnNpb25zIDogMSxcbiAgICAgICAgICAgICAgICAvLyDmlbDmja7nmoTov4fmnJ/ml7bpl7QsIOWNleS9jeenkiwgLTHku6PooajmsLjkuI3ov4fmnJ8uIOWBh+Wmguiuvue9rui/h+acn+aXtumXtOS4uuS4gOW5tCwg5Y2z5Li6IDM2NSAqIDI0ICogMzYwMFxuICAgICAgICAgICAgICAgIHRpbWVUb0xpdmU6IHBhcmFtLnRpbWVvdXRTZWNvbmRzID8gcGFyYW0udGltZW91dFNlY29uZHMgOiAtMSxcblxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dDoge1xuICAgICAgICAgICAgICAgIGNhcGFjaXR5VW5pdDoge1xuICAgICAgICAgICAgICAgICAgICAvLyDkuLrkuobmj5DljYflubblj5Hluqbnoa7kv53pooTnlZnmnIDlsI/or7vlhpnmlbDph4/nmoTphY3nva7pgb/lhY3mnI3liqHlhbHkuqvlj6/og73kuqfnlJ/nmoTotYTmupDnq57kuonkuI3nqLPlrprpl67pophcbiAgICAgICAgICAgICAgICAgICAgcmVhZDogcGFyYW0ucmVzZXJ2ZWRUaHJvdWdocHV0UmVhZCA/IHBhcmFtLnJlc2VydmVkVGhyb3VnaHB1dFJlYWQgOiAwLFxuICAgICAgICAgICAgICAgICAgICB3cml0ZTogcGFyYW0ucmVzZXJ2ZWRUaHJvdWdocHV0V3JpdGUgPyBwYXJhbS5yZXNlcnZlZFRocm91Z2hwdXRXcml0ZSA6IDAsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC51cGRhdGVUYWJsZShwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zfSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8g6YeN572u6KGoXG4gICAgcHVibGljIGFzeW5jIHJlc2V0KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KClcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyBpZ25vcmUgZXJyb3JcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZSgpXG4gICAgfVxufVxuIl19 |
\ | No newline at end of file |