mongoose-transaction-plugin
Version:
A mongoose plugin for transaction-like semantics between multiple documents.
496 lines (495 loc) • 82.8 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
require("source-map-support/register");
const mongoose = require("mongoose");
const Bluebird = require("bluebird");
const _debug = require("debug");
const _ = require("lodash");
const plugin_1 = require("../plugin");
const transaction_1 = require("../transaction");
const utils_1 = require("../utils");
const mockgoose = require('mockgoose');
function spec(assertion) {
return function (done) {
assertion.call(this).then(done, done.fail);
};
}
exports.spec = spec;
function expectToThrow(fn, expected) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield fn();
expect(false).toEqual(true);
}
catch (e) {
expect(() => {
throw e;
}).toThrow();
}
});
}
const debug = _debug('transaction:test');
const conn = mongoose.connection;
describe('Transaction-static', () => {
it('should not allow an unique index', spec(() => __awaiter(this, void 0, void 0, function* () {
expect(() => {
new mongoose.Schema({ name: String }).index('name', { unique: true }).plugin(plugin_1.plugin);
}).toThrowError(`Transaction doesn't support an unique index (name) shardKey (null)`);
expect(() => {
new mongoose.Schema({ type: { type: Number, index: true, unique: true } }).plugin(plugin_1.plugin);
}).toThrowError(`Transaction doesn't support an unique index (type) shardKey (null)`);
expect(() => {
new mongoose.Schema({ type: { type: Number, index: true } }).plugin(plugin_1.plugin);
}).not.toThrowError(`Transaction doesn't support an unique index (type) shardKey (null)`);
expect(() => {
new mongoose.Schema({ name: String }).plugin(plugin_1.plugin).index('name', { unique: true });
}).toThrowError(`Transaction doesn't support an unique index (name) shardKey (null)`);
})));
});
xdescribe('Transaction-static(turned-off)', () => {
it('should not allow an unique index to SchemaType', spec(() => __awaiter(this, void 0, void 0, function* () {
// I have no idea how to override this.
// @kson //2017-01-23
expect(() => {
new mongoose.Schema({ name: String }).plugin(plugin_1.plugin).path('name').index({ unique: true });
}).toThrowError(`Transaction doesn't support an unique index (name)`);
})));
});
describe('Transaction', () => {
let TestPlayer;
beforeAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield mockgoose(mongoose);
yield new Promise(resolve => mongoose.connect('test', resolve));
const testPlayerSchema = new mongoose.Schema({ name: String, age: Number, money: Number });
testPlayerSchema.plugin(plugin_1.plugin);
TestPlayer = conn.model('TestPlayer', testPlayerSchema);
transaction_1.Transaction.initialize(conn);
})));
beforeEach(spec(() => __awaiter(this, void 0, void 0, function* () {
const testPlayer1 = new TestPlayer({ name: 'ekim', age: 10, money: 0 });
const testPlayer2 = new TestPlayer({ name: 'wokim', age: 50, money: 0 });
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
yield t.insertDoc(testPlayer1);
yield t.insertDoc(testPlayer2);
}));
})));
it('should index state', spec(() => __awaiter(this, void 0, void 0, function* () {
const indexes = transaction_1.Transaction.getModel.schema.indexes();
const [fields, options] = indexes[0];
expect(fields.state).toEqual(1);
expect(options.background).toBeTruthy();
})));
it('should ignore calling begin() twice in silent', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
yield t.begin();
const d = yield t.findOne(TestPlayer, { name: 'ekim' });
expect(d.name).toEqual('ekim');
}));
})));
it('could use write lock', spec(() => __awaiter(this, void 0, void 0, function* () {
const options = {
transaction: true,
__t: new mongoose.Types.ObjectId()
};
const doc = yield TestPlayer.findOne({ name: 'ekim' }, {}, options).exec();
expect(doc['__t']).toBeDefined();
debug('__t is %s', doc['__t']);
debug('save document to detach __t');
const saved = yield doc.save();
expect(saved['__t']).toBeUndefined();
})));
it('should not allow `Model.findOne` with transaction out of a transaction disposer', spec(() => __awaiter(this, void 0, void 0, function* () {
try {
yield TestPlayer.findOne({ name: 'ekim' }, {}, { transaction: true }).exec();
expect(true).toEqual(false);
}
catch (e) {
expect(() => {
throw e;
}).toThrow();
}
})));
it('could commit two documents in same transaction', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((tx) => __awaiter(this, void 0, void 0, function* () {
const testPlayer = yield tx.findOne(TestPlayer, { name: 'wokim' });
debug('locking success: %o', testPlayer);
testPlayer.money += 600;
}));
expect(1).toBe(1);
})));
it('can not save without lock', spec(() => __awaiter(this, void 0, void 0, function* () {
const doc = yield TestPlayer.findOne({ name: 'ekim' }, {}).exec();
expect(doc['__t']).toBeUndefined();
try {
yield doc.save();
expect(true).toEqual(false);
}
catch (e) {
expect(true).toEqual(true);
}
})));
it('duplicate findOne with One Transaction', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const doc = yield t.findOne(TestPlayer, { name: 'ekim' });
expect(doc['__t']).toBeDefined();
doc.money += 500;
const secondTry = yield t.findOne(TestPlayer, { name: 'ekim' });
secondTry.money += 1000;
}));
const doc = yield TestPlayer.findOne({ name: 'ekim' }, {}).exec();
expect(doc.money).toBe(1500);
})));
it('duplicate findOne with other conditions', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const doc = yield t.findOne(TestPlayer, { name: 'ekim' });
expect(doc['__t']).toBeDefined();
doc.money += 500;
const sameButDiffConditionDoc = yield t.findOne(TestPlayer, { age: 10 });
sameButDiffConditionDoc.money += 1000;
}));
const doc = yield TestPlayer.findOne({ name: 'ekim' }, {}).exec();
expect(doc.money).toBe(1500);
})));
it('should save new document without transaction', spec(() => __awaiter(this, void 0, void 0, function* () {
const doc = new TestPlayer({ name: 'newbie', age: 1 });
try {
yield doc.save();
expect(true).toEqual(true);
}
catch (e) {
expect(e).toBeUndefined();
}
})));
it('should retry when it finds a live transaction', done => {
function addMoney(name, money) {
return transaction_1.Transaction.scope(t => {
return t.findOne(TestPlayer, { name: name })
.then(doc => {
doc.money += money;
return doc;
});
});
}
return Bluebird.all([
addMoney('ekim', 100),
addMoney('ekim', 100),
addMoney('ekim', 100),
addMoney('ekim', 100)
])
.then((results) => {
return Bluebird.resolve(TestPlayer.findOne({ name: 'ekim' }, {}).exec());
})
.then(doc => {
expect(doc.money).toBe(400);
done();
});
});
it('should evaluate the condition on each retry', spec(() => __awaiter(this, void 0, void 0, function* () {
function grow() {
return __awaiter(this, void 0, void 0, function* () {
let growth = false;
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const wokim = yield t.findOne(TestPlayer, { age: 50 });
if (wokim) {
growth = true;
wokim.age++;
}
}));
return growth;
});
}
const result = _.countBy(yield Bluebird.all([grow(), grow()]));
expect(result['true']).toEqual(1);
expect(result['false']).toEqual(1);
})));
it('delete all document', spec(() => __awaiter(this, void 0, void 0, function* () {
function removePlayerDoc(name) {
return __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const doc = yield t.findOne(TestPlayer, { name: name });
yield t.removeDoc(doc);
}));
});
}
try {
yield Bluebird.all([removePlayerDoc('ekim'), removePlayerDoc('wokim')]);
expect(true).toEqual(true);
}
catch (e) {
expect(true).toEqual(false);
}
})));
it('should throw an error to resolve an expired transaction with no history', spec(() => __awaiter(this, void 0, void 0, function* () {
const oldTransaction = new transaction_1.Transaction.getModel();
oldTransaction._id = utils_1.ObjectId.get(+new Date('2016-01-01'));
yield TestPlayer.collection.update({ name: 'ekim' }, { $set: { __t: oldTransaction._id } });
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
try {
yield t.findOne(TestPlayer, { name: 'ekim' });
expect(true).toEqual(false);
}
catch (e) {
expect(() => {
throw e;
}).toThrowError('There is no transaction history.');
}
}));
})));
it('should cancel expired transaction which is stated as `init`', spec(() => __awaiter(this, void 0, void 0, function* () {
const oldTransaction = new transaction_1.Transaction.getModel();
oldTransaction._id = utils_1.ObjectId.get(+new Date('2016-01-01'));
oldTransaction.state = 'init';
yield oldTransaction.save();
const savedOldTransaction = yield transaction_1.Transaction.getModel.findOne({ _id: oldTransaction._id });
expect(savedOldTransaction.state).toEqual('init');
yield TestPlayer.collection.update({ name: 'ekim' }, { $set: { __t: oldTransaction._id } });
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
yield t.findOne(TestPlayer, { name: 'ekim' });
const canceledOldTransaction = yield transaction_1.Transaction.getModel.findOne({ _id: oldTransaction._id });
expect(canceledOldTransaction.state).toEqual('canceled');
}));
})));
it('should recommit when it finds an old pending transaction', spec(() => __awaiter(this, void 0, void 0, function* () {
const oldTransaction = new transaction_1.Transaction.getModel();
oldTransaction._id = utils_1.ObjectId.get(+new Date(new Date().getTime() - (1000 * 60 * 60)));
oldTransaction.state = 'pending';
const ekim = yield TestPlayer.findOne({ name: 'ekim' });
oldTransaction.history.push({
col: TestPlayer.collection.name,
oid: ekim._id,
shardKeyName: 'name',
shardKey: ekim.name,
op: 'update',
query: JSON.stringify({ $set: { money: 1000 } })
});
yield oldTransaction.save();
yield TestPlayer.collection.update({ name: 'ekim' }, { $set: { __t: oldTransaction._id } });
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const doc = yield t.findOne(TestPlayer, { name: 'ekim' });
expect(doc.money).toEqual(1000);
const transaction = yield transaction_1.Transaction.getModel.findOne({ _id: oldTransaction._id });
if (transaction) {
expect(transaction.state).toEqual('committed');
}
else {
expect(yield transaction_1.Transaction.getModel.count({ _id: oldTransaction._id })).toEqual(0);
}
}));
})));
it('should cancel transaction if the handler throws', spec(() => __awaiter(this, void 0, void 0, function* () {
let tid;
try {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
tid = t._id;
const doc = yield t.findOne(TestPlayer, { name: 'ekim' });
doc.money += 1000;
throw new Error('hahaha');
}));
}
catch (e) {
const transaction = yield transaction_1.Transaction.getModel.findOne({ _id: tid });
expect(transaction).toEqual(null);
const ekim = yield TestPlayer.findOne({ name: 'ekim' });
expect(ekim.money).toEqual(0);
}
})));
afterEach(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mockgoose.reset(() => resolve()));
})));
afterAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mongoose.unmock(resolve));
yield new Promise(resolve => mongoose.disconnect(resolve));
})));
});
describe('Transaction (_id uniqueness)', () => {
let TestUniqId;
beforeAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield mockgoose(mongoose);
yield new Promise(resolve => mongoose.connect('test', resolve));
const testUniqIdSchema = new mongoose.Schema({ name: String, type: String });
testUniqIdSchema.plugin(plugin_1.plugin);
TestUniqId = conn.model('TestUniqIdx', testUniqIdSchema);
transaction_1.Transaction.initialize(conn);
})));
afterEach(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mockgoose.reset(() => resolve()));
})));
afterAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mongoose.unmock(resolve));
yield new Promise(resolve => mongoose.disconnect(resolve));
})));
it('SHOULD find _id conflict', spec(() => __awaiter(this, void 0, void 0, function* () {
yield expectToThrow(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const oid = new mongoose.Types.ObjectId();
yield t.insertDoc(new TestUniqId({ _id: oid }));
yield t.insertDoc(new TestUniqId({ _id: oid }));
}));
}));
expect(yield TestUniqId.count({})).toEqual(0);
})));
it('COULD update a doc after t.insertDoc', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
const a = new TestUniqId();
yield t.insertDoc(a);
a.name = 'dad';
}));
const a = yield TestUniqId.findOne();
expect(a.name).toEqual('dad');
})));
it('SHOULD start rollback when find _id conflict another transaction', spec(() => __awaiter(this, void 0, void 0, function* () {
const oid = new mongoose.Types.ObjectId();
yield transaction_1.Transaction.scope((t1) => __awaiter(this, void 0, void 0, function* () {
yield t1.insertDoc(new TestUniqId({ _id: oid }));
const transactionModel = new transaction_1.Transaction.getModel();
const doc1 = yield transactionModel.collection.findOne({ _id: t1._id });
expect(doc1).not.toBeNull();
expect(doc1.rollback.length).toEqual(1);
yield transaction_1.Transaction.scope((t2) => __awaiter(this, void 0, void 0, function* () {
yield t2.insertDoc(new TestUniqId({ _id: oid }));
}));
const doc2 = yield transactionModel.collection.findOne({ _id: t1._id });
expect(doc2).toBeNull();
}));
expect(yield TestUniqId.count({})).toEqual(1);
})));
});
describe('Transcation (recommit)', () => {
let TestRecommit;
beforeAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield mockgoose(mongoose);
yield new Promise(resolve => mongoose.connect('test', resolve));
const testRecommitSchema = new mongoose.Schema({ name: String, opts: mongoose.Schema.Types.Mixed });
testRecommitSchema.plugin(plugin_1.plugin);
TestRecommit = conn.model('TestRecommit', testRecommitSchema);
transaction_1.Transaction.initialize(conn);
})));
afterEach(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mockgoose.reset(() => resolve()));
})));
afterAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mongoose.unmock(resolve));
yield new Promise(resolve => mongoose.disconnect(resolve));
})));
it('SHOULD be able to recommit new doc', spec(() => __awaiter(this, void 0, void 0, function* () {
const transaction = new transaction_1.Transaction();
const t = new transaction_1.Transaction.getModel();
transaction.transaction = yield t.save();
const tui = new TestRecommit();
yield transaction.insertDoc(tui);
tui.name = 'baby';
tui.opts = { 'name': 'value', 'check': true, 'numeral': 3 };
yield transaction_1.Transaction.makeHistory(transaction.participants, t);
yield transaction_1.Transaction.recommit(t);
const a = yield TestRecommit.findOne();
expect(a.name).toEqual('baby');
expect(a.opts.name).toEqual('value');
expect(a.opts.check).toEqual(true);
expect(a.opts.numeral).toEqual(3);
})));
it('SHOULD be able to recommit new doc without delta', spec(() => __awaiter(this, void 0, void 0, function* () {
const transaction = new transaction_1.Transaction();
const t = new transaction_1.Transaction.getModel();
transaction.transaction = yield t.save();
const tui = new TestRecommit({ name: 'dad', opts: { name: 'recommit' } });
yield transaction.insertDoc(tui);
yield transaction_1.Transaction.makeHistory(transaction.participants, t);
yield transaction_1.Transaction.recommit(t);
const a = yield TestRecommit.findOne();
expect(a.name).toEqual('dad');
expect(a.opts.name).toEqual('recommit');
})));
it('SHOULD be able to remove doc', spec(() => __awaiter(this, void 0, void 0, function* () {
const before = new TestRecommit();
yield before.save();
const transaction = new transaction_1.Transaction();
const t = new transaction_1.Transaction.getModel();
transaction.transaction = yield t.save();
const after = yield transaction.findOne(TestRecommit, {});
yield transaction.removeDoc(after);
yield transaction_1.Transaction.makeHistory(transaction.participants, t);
yield transaction_1.Transaction.recommit(t);
expect(yield TestRecommit.count({})).toEqual(0);
})));
it('SHOULD be no __t when the new doc is committed', spec(() => __awaiter(this, void 0, void 0, function* () {
const transaction = new transaction_1.Transaction();
const t = new transaction_1.Transaction.getModel();
transaction.transaction = yield t.save();
const tui = new TestRecommit();
yield transaction.insertDoc(tui);
tui.name = 'baby';
tui.opts = { 'name': 'value', 'check': true, 'numeral': 3 };
yield transaction_1.Transaction.makeHistory(transaction.participants, t);
yield transaction_1.Transaction.recommit(t);
const doc = yield TestRecommit.findOne();
expect(doc['__t']).toBeUndefined();
})));
it('SHOULD be able to rollback new doc', spec(() => __awaiter(this, void 0, void 0, function* () {
const transaction = new transaction_1.Transaction();
const t = new transaction_1.Transaction.getModel();
transaction.transaction = yield t.save();
const tui = new TestRecommit();
yield transaction.insertDoc(tui);
tui.name = 'rollbackDoc';
tui.opts = { 'name': 'value', 'check': true, 'numeral': 3 };
const transactionModel = new transaction_1.Transaction.getModel();
const transactionDoc = yield transactionModel.collection.findOne({});
expect(transactionDoc.history.length).toEqual(0);
expect(transactionDoc.rollback.length).toEqual(1);
expect(transactionDoc.rollback[0].oid.toString()).toEqual(tui._id.toString());
const doc1 = yield TestRecommit.findOne();
expect(doc1).not.toBeNull();
yield transaction_1.Transaction.recommit(t);
const doc2 = yield TestRecommit.findOne();
expect(doc2).toBeNull();
})));
});
describe('Transcation any Type ID', () => {
let TestAnyIdDoc;
beforeAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield mockgoose(mongoose);
yield new Promise(resolve => mongoose.connect('test', resolve));
const testSchema = new mongoose.Schema({ _id: String, name: String, opts: { status: Number } });
testSchema.plugin(plugin_1.plugin);
TestAnyIdDoc = conn.model('TestAnyId', testSchema);
transaction_1.Transaction.initialize(conn);
})));
afterEach(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mockgoose.reset(() => resolve()));
})));
afterAll(spec(() => __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => mongoose.unmock(resolve));
yield new Promise(resolve => mongoose.disconnect(resolve));
})));
beforeEach(spec(() => __awaiter(this, void 0, void 0, function* () {
const testDoc1 = new TestAnyIdDoc({ _id: 'jipark', name: 'Park Jiho', opts: { status: 1 } });
const testDoc2 = new TestAnyIdDoc({ _id: 'act', name: 'Asia Central Tech', opts: { status: 2 } });
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
yield t.insertDoc(testDoc1);
yield t.insertDoc(testDoc2);
}));
})));
it('SHOULD check Data', spec(() => __awaiter(this, void 0, void 0, function* () {
expect(yield TestAnyIdDoc.count({})).toEqual(2);
const doc1 = yield TestAnyIdDoc.findOne({ _id: 'jipark' }, {}).exec();
const doc2 = yield TestAnyIdDoc.findOne({ _id: 'act' }, {}).exec();
expect(doc1.name).toEqual('Park Jiho');
expect(doc2.name).toEqual('Asia Central Tech');
})));
it('should ignore calling begin() twice in silent', spec(() => __awaiter(this, void 0, void 0, function* () {
yield transaction_1.Transaction.scope((t) => __awaiter(this, void 0, void 0, function* () {
yield t.begin();
const d = yield t.findOne(TestAnyIdDoc, { _id: 'jipark' });
expect(d.name).toEqual('Park Jiho');
}));
})));
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy8uLi9zcmMvc3BlYy90cmFuc2FjdGlvbi1zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx1Q0FBcUM7QUFDckMscUNBQXFDO0FBQ3JDLHFDQUFxQztBQUNyQyxnQ0FBZ0M7QUFDaEMsNEJBQTRCO0FBRTVCLHNDQUFtQztBQUNuQyxnREFBNkM7QUFDN0Msb0NBQW9DO0FBRXBDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUV2QyxTQUFnQixJQUFJLENBQUMsU0FBOEI7SUFDakQsT0FBTyxVQUFVLElBQUk7UUFDbkIsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3QyxDQUFDLENBQUM7QUFDSixDQUFDO0FBSkQsb0JBSUM7QUFFRCxTQUFlLGFBQWEsQ0FBQyxFQUFFLEVBQUUsUUFBYzs7UUFDN0MsSUFBSTtZQUNGLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzdCO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsR0FBRyxFQUFFO2dCQUNWLE1BQU0sQ0FBQyxDQUFDO1lBQ1YsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDZDtJQUNILENBQUM7Q0FBQTtBQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBQ3pDLE1BQU0sSUFBSSxHQUF3QixRQUFRLENBQUMsVUFBVSxDQUFDO0FBRXRELFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7SUFDbEMsRUFBRSxDQUFDLGtDQUFrQyxFQUFFLElBQUksQ0FBQyxHQUFTLEVBQUU7UUFDckQsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNWLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsZUFBTSxDQUFDLENBQUM7UUFDckYsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7UUFFdEYsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNWLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxlQUFNLENBQUMsQ0FBQztRQUM1RixDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsb0VBQW9FLENBQUMsQ0FBQztRQUV0RixNQUFNLENBQUMsR0FBRyxFQUFFO1lBQ1YsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxlQUFNLENBQUMsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7UUFFMUYsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNWLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxlQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7UUFDckYsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7SUFDeEYsQ0FBQyxDQUFBLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyxDQUFDLENBQUM7QUFFSCxTQUFTLENBQUMs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