diff --git a/src/backend/controllers/admin.ts b/src/backend/controllers/admin.ts index cf03482..f9e63cc 100644 --- a/src/backend/controllers/admin.ts +++ b/src/backend/controllers/admin.ts @@ -1,10 +1,13 @@ /** - * バージョン情報など、サーバーのメタデータを返すAPI + * Admin API * @author Xeltica */ -import { Get, JsonController } from 'routing-controllers'; +import { BadRequestError, CurrentUser, Get, JsonController, OnUndefined, Post } from 'routing-controllers'; +import { IUser } from '../../common/types/user'; import { config } from '../../config'; +import { work } from '../services/worker'; +import * as Store from '../store'; @JsonController('/admin') export class AdminController { @@ -15,4 +18,24 @@ export class AdminController { acct: `@${username}@${host}`, }; } + + @Get('/misshai/error') getMisshaiError(@CurrentUser({ required: true }) user: IUser) { + if (!user.isAdmin) { + throw new BadRequestError('Not an Admin'); + } + + return Store.getState().misshaiWorkerRecentError; + } + + @OnUndefined(204) + @Post('/misshai/start') startMisshai(@CurrentUser({ required: true }) user: IUser) { + if (!user.isAdmin) { + throw new BadRequestError('Not an Admin'); + } + if (Store.getState().nowCalculating) { + throw new BadRequestError('Already started'); + } + + work(); + } } diff --git a/src/backend/services/worker.ts b/src/backend/services/worker.ts index 1dd3e53..4718f9e 100644 --- a/src/backend/services/worker.ts +++ b/src/backend/services/worker.ts @@ -13,9 +13,13 @@ import * as Store from '../store'; import { User } from '../models/entities/user'; export default (): void => { - cron.schedule('0 0 0 * * *', async () => { - Store.dispatch({ nowCalculating: true }); + cron.schedule('0 0 0 * * *', work); +}; +export const work = async () => { + Store.dispatch({ nowCalculating: true }); + + try { const users = await Users.find({ alertMode: Not('nothing') }); for (const user of users) { await update(user).catch(e => handleError(user, e)); @@ -24,9 +28,13 @@ export default (): void => { return delay(3000); } } - + Store.dispatch({ misshaiWorkerRecentError: null }); + } catch (e) { + const msg = String(e instanceof Error ? e.stack : e); + Store.dispatch({ misshaiWorkerRecentError: msg }); + } finally { Store.dispatch({ nowCalculating: false }); - }); + } }; /** diff --git a/src/backend/store.ts b/src/backend/store.ts index e24a0bc..7291067 100644 --- a/src/backend/store.ts +++ b/src/backend/store.ts @@ -7,6 +7,7 @@ */ const defaultState: State = { nowCalculating: false, + misshaiWorkerRecentError: null, }; let _state: Readonly = defaultState; @@ -16,6 +17,7 @@ let _state: Readonly = defaultState; */ export type State = { nowCalculating: boolean, + misshaiWorkerRecentError: string | null, }; /** diff --git a/src/frontend/components/AdminPage.tsx b/src/frontend/components/AdminPage.tsx index b48d424..5df8744 100644 --- a/src/frontend/components/AdminPage.tsx +++ b/src/frontend/components/AdminPage.tsx @@ -6,6 +6,7 @@ import { Skeleton } from './Skeleton'; import { IAnnouncement } from '../../common/types/announcement'; import { $delete, $get, $post, $put } from '../misc/api'; import { Card } from './Card'; +import { showModal } from '../store/slices/screen'; export const AdminPage: React.VFC = () => { @@ -19,6 +20,8 @@ export const AdminPage: React.VFC = () => { const [draftTitle, setDraftTitle] = useState(''); const [draftBody, setDraftBody] = useState(''); + const [misshaiError, setMisshaiError] = useState(null); + const submitAnnouncement = async () => { if (selectedAnnouncement) { await $put('announcements', { @@ -52,6 +55,22 @@ export const AdminPage: React.VFC = () => { setAnnouncements(announcements ?? []); setAnnouncementsLoaded(true); }); + $get('admin/misshai/error').then(setMisshaiError); + }; + + const onClickStartMisshaiAlertWorkerButton = () => { + $post('admin/misshai/start').then(() => { + dispatch(showModal({ + type: 'dialog', + message: '開始', + })); + }).catch((e) => { + dispatch(showModal({ + type: 'dialog', + icon: 'error', + message: e.message, + })); + }); }; /** @@ -166,6 +185,16 @@ export const AdminPage: React.VFC = () => { )} +
+

Misshai

+
+ +

直近のワーカーエラー

+
{misshaiError ?? 'なし'}
+
+
) } @@ -174,3 +203,7 @@ export const AdminPage: React.VFC = () => { }; +function dispatch(arg0: any) { + throw new Error('Function not implemented.'); +} +