From eac431a055b975bde83445e6f73ebe255e525c24 Mon Sep 17 00:00:00 2001 From: proshunsuke Date: Sun, 17 Oct 2021 16:35:13 +0900 Subject: [PATCH 1/2] =?UTF-8?q?1=E3=81=A4=E3=81=AE=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=82=92=E7=99=BB=E9=8C=B2=E3=81=97=E7=B5=82=E3=82=8F?= =?UTF-8?q?=E3=81=A3=E3=81=9F=E3=82=89=E6=AC=A1=E3=81=AE=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=82=92=E3=82=BB=E3=83=83=E3=83=88=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=B8=80=E6=97=A6=E7=B5=82=E4=BA=86=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/schedule.ts | 9 +++++++-- src/sites/siteSchedule.ts | 38 ++++++++++++++++++++++++++++++++++---- tests/schedule.test.ts | 23 ++++++++++++++--------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/schedule.ts b/src/schedule.ts index 9d66efd..24ff6c0 100644 --- a/src/schedule.ts +++ b/src/schedule.ts @@ -9,8 +9,13 @@ export default class Schedule { new KeyakiSiteSchedule(), new SakuraSiteSchedule(), ]; - for await (const siteSchedule of siteScheduleList) { - await siteSchedule.setSiteSchedule(startDate); + for (let i = 0; i < siteScheduleList.length; i++) { + const executed = await siteScheduleList[i].setSiteSchedule( + startDate, + siteScheduleList[i + 1] + ); + // スケジュール登録をした場合は即終了。しなかった場合は既に登録済みなので次のサイトのスケジュール登録に進む + if (executed) return; } } } diff --git a/src/sites/siteSchedule.ts b/src/sites/siteSchedule.ts index d9e7181..7d2dbfe 100644 --- a/src/sites/siteSchedule.ts +++ b/src/sites/siteSchedule.ts @@ -4,15 +4,31 @@ import Trigger, { TERMINATION_MINUTES } from '../lib/trigger'; import { SiteCalendarInterface } from '../calendarInterface'; export interface SiteScheduleInterface { - setSiteSchedule(startDate: dayjs.Dayjs): Promise; + setSiteSchedule( + startDate: dayjs.Dayjs, + nextSiteSchedule?: SiteScheduleInterface + ): Promise; + siteCalendarUrl(): string; + siteCalendarIds(): SiteCalendarInterface[]; + siteName(): string; } export default abstract class SiteSchedule implements SiteScheduleInterface { - async setSiteSchedule(startDate: dayjs.Dayjs): Promise { - if (!this.doesExecute()) return; + /** + * スケジュール登録をした場合はtrue, しなかった場合はfalseを返す + * + * @param {dayjs.Dayjs} startDate + * @param nextSiteSchedule + * @returns {Promise} + */ + async setSiteSchedule( + startDate: dayjs.Dayjs, + nextSiteSchedule?: SiteScheduleInterface + ): Promise { + if (!this.doesExecute()) return false; console.info(`${this.siteName()}の予定を更新します`); const beginningOfNexYearMonth = dayjs().startOf('month').add(1, 'year'); let targetBeginningOfMonth = SiteSchedule.getTargetBeginningOfMonth(); @@ -32,12 +48,26 @@ export default abstract class SiteSchedule implements SiteScheduleInterface { 'YYYY-MM-DD' )}, 次実行するサイト: ${this.siteName()}` ); - return; + return true; } } + + if (nextSiteSchedule) { + const thisMonth = dayjs().startOf('month'); + Trigger.setTrigger(thisMonth, nextSiteSchedule.siteName()); + console.info( + `${this.siteName()}の全てのスケジュール作成が完了したので次のトリガーをセットして終了します。次実行開始する月: ${thisMonth.format( + 'YYYY-MM-DD' + )}, 次実行するサイト: ${nextSiteSchedule.siteName()}` + ); + return true; + } + Trigger.deleteTargetDateProperty(); Trigger.deleteTargetSiteNameProperty(); Trigger.deleteTriggers(); + + return true; } /** diff --git a/tests/schedule.test.ts b/tests/schedule.test.ts index b50043a..119a879 100644 --- a/tests/schedule.test.ts +++ b/tests/schedule.test.ts @@ -12,14 +12,14 @@ describe('setSchedule', (): void => { jest.spyOn(console, 'info').mockImplementation(); jest.resetAllMocks(); }); - it('setScheduleが24回呼ばれ各サイト1年分の予定が作成されること', async () => { + it('サイトの1年分のスケジュールが登録された場合は次のスケジュール登録は実行されずsetScheduleは12回実行されること', async () => { await Schedule.setSchedule(dayjs()); - expect(OneMonthSchedule.setSchedule).toBeCalledTimes(24); + expect(OneMonthSchedule.setSchedule).toBeCalledTimes(12); }); it('propertiesに日付がセットされていた場合にその日付からスケジュール登録が始まること', async () => { Trigger.getTargetDateProperty = jest.fn().mockReturnValueOnce('2020-01-01'); await Schedule.setSchedule(dayjs()); - expect(OneMonthSchedule.setSchedule).toBeCalledTimes(23); + expect(OneMonthSchedule.setSchedule).toBeCalledTimes(11); }); it('propertiesにサイト名がセットされていた場合にそのサイトからスケジュール登録が始まること', async () => { Trigger.getTargetSiteNameProperty = jest @@ -35,18 +35,23 @@ describe('setSchedule', (): void => { .mockReturnValue(true); Trigger.setTrigger = jest.fn().mockReturnThis(); await Schedule.setSchedule(dayjs()); - expect(OneMonthSchedule.setSchedule).toBeCalledTimes(3); - expect(Trigger.setTrigger).toBeCalledTimes(2); + expect(OneMonthSchedule.setSchedule).toBeCalledTimes(2); + expect(Trigger.setTrigger).toBeCalledTimes(1); }); - it('指定時間内に全て実行出来たらdeleteTargetDatePropertyとdeleteTriggersが呼ばれること', async () => { + it('次にスケジュール登録するサイトが存在しない場合にdeleteTargetDatePropertyとdeleteTriggersが呼ばれること', async () => { Trigger.hasExceededTerminationMinutes = jest.fn().mockReturnValue(false); Trigger.setTrigger = jest.fn().mockReturnThis(); Trigger.deleteTargetDateProperty = jest.fn().mockReturnThis(); + Trigger.deleteTargetSiteNameProperty = jest.fn().mockReturnThis(); Trigger.deleteTriggers = jest.fn().mockReturnThis(); + Trigger.getTargetSiteNameProperty = jest + .fn() + .mockReturnValueOnce('sakurazaka'); await Schedule.setSchedule(dayjs()); - expect(OneMonthSchedule.setSchedule).toBeCalledTimes(24); + expect(OneMonthSchedule.setSchedule).toBeCalledTimes(12); expect(Trigger.setTrigger).not.toBeCalled(); - expect(Trigger.deleteTargetDateProperty).toBeCalledTimes(2); - expect(Trigger.deleteTriggers).toBeCalledTimes(2); + expect(Trigger.deleteTargetDateProperty).toBeCalledTimes(1); + expect(Trigger.deleteTargetSiteNameProperty).toBeCalledTimes(1); + expect(Trigger.deleteTriggers).toBeCalledTimes(1); }); }); From 781d286007df5aa8c0f1ff79f5dc42b068e82318 Mon Sep 17 00:00:00 2001 From: proshunsuke Date: Sun, 17 Oct 2021 16:37:59 +0900 Subject: [PATCH 2/2] =?UTF-8?q?SITE=5FNAME=E3=82=92=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=81=A8GAS=E3=81=AEgetProperty('site=5Fname?= =?UTF-8?q?')=E3=81=AE=E5=80=A4=E3=82=92=E6=8C=87=E5=AE=9A=E5=87=BA?= =?UTF-8?q?=E6=9D=A5=E3=82=8B=E3=80=82=E3=81=9D=E3=81=AE=E3=82=B5=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=81=8B=E3=82=89=E3=82=B9=E3=82=B1=E3=82=B8=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E7=99=BB=E9=8C=B2=E3=81=8C=E5=A7=8B=E3=81=BE?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=AA=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +++- src/lib/trigger.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8df592e..3081ca3 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +SITE_NAME=keyakizaka + setup: $(MAKE) yarn/install @@ -26,7 +28,7 @@ run: yarn clasp run execute run/local: - node -e 'require("./dist/index.js");global.setSchedule();' + SITE_NAME=$(SITE_NAME) node -e 'require("./dist/index.js");global.setSchedule();' open: yarn clasp open diff --git a/src/lib/trigger.ts b/src/lib/trigger.ts index 0fb4ef5..3d129d7 100644 --- a/src/lib/trigger.ts +++ b/src/lib/trigger.ts @@ -53,6 +53,7 @@ export default class Trigger { * @returns {string | null} */ static getTargetSiteNameProperty(): string | null { + if (process.env.SITE_NAME) return process.env.SITE_NAME; if (process.env.ENV !== 'production') return null; const properties = PropertiesService.getScriptProperties(); return properties.getProperty(TARGET_SITE_NAME_KEY);