@chevre/domain
Version:
Chevre Domain Library for Node.js
150 lines (149 loc) • 6.03 kB
JavaScript
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 });
const createDebug = require("debug");
const moment = require("moment");
const factory = require("../../factory");
const debug = createDebug('chevre-domain:repo');
/**
* 上映イベントに対する座席ごとの在庫状況を保管するリポジトリ
*/
class RedisRepository {
constructor(redisClient) {
this.redisClient = redisClient;
}
/**
* 座席をロックする
*/
lock(lockKey) {
return __awaiter(this, void 0, void 0, function* () {
debug('locking...', lockKey);
const key = `${RedisRepository.KEY_PREFIX}:${lockKey.eventId}`;
const value = lockKey.holder;
const multi = this.redisClient.multi();
const fields = lockKey.offers.map((offer) => `${offer.seatSection}:${offer.seatNumber}`);
fields.forEach((field) => {
multi.hsetnx(key, field, value);
});
const results = yield new Promise((resolve, reject) => {
multi.expireat(key, moment(lockKey.expires).unix())
.exec((err, reply) => {
debug('reply:', reply);
if (err !== null) {
reject(err);
}
else {
resolve(reply);
}
});
});
const lockedFields = [];
results.slice(0, fields.length).forEach((r, index) => {
if (r === 1) {
lockedFields.push(fields[index]);
}
});
debug('locked fields:', lockedFields);
const lockedAll = lockedFields.length === fields.length;
debug('lockedAll?', lockedAll);
if (!lockedAll) {
if (lockedFields.length > 0) {
// 全て仮押さえできなければ仮押さえできたものは解除
yield new Promise((resolve, reject) => {
this.redisClient.multi()
.hdel(key, lockedFields)
.exec((err, reply) => {
debug('reply:', reply);
if (err !== null) {
reject(err);
}
else {
resolve();
}
});
});
}
throw new factory.errors.AlreadyInUse('', [], 'Seat number already hold');
}
});
}
/**
* 座席ロックを解除する
*/
unlock(params) {
return __awaiter(this, void 0, void 0, function* () {
const key = `${RedisRepository.KEY_PREFIX}:${params.eventId}`;
const field = `${params.offer.seatSection}:${params.offer.seatNumber}`;
yield new Promise((resolve, reject) => {
this.redisClient.multi()
.hdel(key, field)
.exec((err, reply) => {
debug('reply:', reply);
if (err !== null) {
reject(err);
}
else {
resolve();
}
});
});
});
}
/**
* 空席でない座席を検索する
*/
findUnavailableOffersByEventId(params) {
return __awaiter(this, void 0, void 0, function* () {
const key = `${RedisRepository.KEY_PREFIX}:${params.eventId}`;
return new Promise((resolve, reject) => {
this.redisClient.hgetall(key, (err, reply) => {
debug('reply:', reply);
if (err !== null) {
reject(err);
}
else {
let offers = [];
if (reply !== null) {
offers = Object.keys(reply).map((field) => {
const seatSection = field.split(':')[0];
const seatNumber = field.split(':')[1];
return { seatSection, seatNumber };
});
}
resolve(offers);
}
});
});
});
}
/**
* 保持者を取得する
*/
getHolder(params) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const key = `${RedisRepository.KEY_PREFIX}:${params.eventId}`;
const field = `${params.offer.seatSection}:${params.offer.seatNumber}`;
this.redisClient.hget(key, field, (err, result) => {
debug('result:', err, result);
if (err !== null) {
reject(err);
}
else {
// tslint:disable-next-line:no-magic-numbers
resolve(result);
}
});
});
});
}
}
RedisRepository.KEY_PREFIX = 'chevre:itemAvailability:screeningEvent';
exports.RedisRepository = RedisRepository;
;