UNPKG

@chevre/domain

Version:

Chevre Domain Library for Node.js

150 lines (149 loc) 6.03 kB
"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 }); 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;