管理画面からアラートワーカーを起動できるように

This commit is contained in:
Xeltica 2021-10-18 00:58:09 +09:00
parent 81c2dcb35a
commit f64c0d0bd5
4 changed files with 72 additions and 6 deletions

View File

@ -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();
}
}

View File

@ -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<AlertMode>('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 });
});
}
};
/**

View File

@ -7,6 +7,7 @@
*/
const defaultState: State = {
nowCalculating: false,
misshaiWorkerRecentError: null,
};
let _state: Readonly<State> = defaultState;
@ -16,6 +17,7 @@ let _state: Readonly<State> = defaultState;
*/
export type State = {
nowCalculating: boolean,
misshaiWorkerRecentError: string | null,
};
/**

View File

@ -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<string | null>(null);
const submitAnnouncement = async () => {
if (selectedAnnouncement) {
await $put('announcements', {
@ -52,6 +55,22 @@ export const AdminPage: React.VFC = () => {
setAnnouncements(announcements ?? []);
setAnnouncementsLoaded(true);
});
$get<string | null>('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 = () => {
)}
</Card>
</article>
<article>
<h2>Misshai</h2>
<div className="vstack">
<button className="btn danger" onClick={onClickStartMisshaiAlertWorkerButton}>
</button>
<h3></h3>
<pre><code>{misshaiError ?? 'なし'}</code></pre>
</div>
</article>
</>
)
}
@ -174,3 +203,7 @@ export const AdminPage: React.VFC = () => {
};
function dispatch(arg0: any) {
throw new Error('Function not implemented.');
}