server: use time constants
This commit is contained in:
parent
66a7c62342
commit
9e2553909e
24 changed files with 78 additions and 58 deletions
|
@ -1,9 +1,10 @@
|
|||
import Xev from 'xev';
|
||||
import { deliverQueue, inboxQueue } from '@/queue/queues.js';
|
||||
import { SECOND } from '@/const.js';
|
||||
|
||||
const ev = new Xev();
|
||||
|
||||
const interval = 10000;
|
||||
const interval = 10 * SECOND;
|
||||
|
||||
/**
|
||||
* Report queue stats regularly
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// https://github.com/typeorm/typeorm/issues/2400
|
||||
import pg from 'pg';
|
||||
import { SECOND } from '@/const.js';
|
||||
|
||||
pg.types.setTypeParser(20, Number);
|
||||
|
||||
import { Logger, DataSource } from 'typeorm';
|
||||
|
@ -182,7 +184,7 @@ export const db = new DataSource({
|
|||
password: config.db.pass,
|
||||
database: config.db.db,
|
||||
extra: {
|
||||
statement_timeout: 1000 * 10,
|
||||
statement_timeout: 10 * SECOND,
|
||||
...config.db.extra,
|
||||
},
|
||||
synchronize: process.env.NODE_ENV === 'test',
|
||||
|
@ -234,7 +236,7 @@ export async function resetDb() {
|
|||
if (i === 3) {
|
||||
throw e;
|
||||
} else {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
await new Promise(resolve => setTimeout(resolve, SECOND));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { promisify } from 'node:util';
|
||||
import redisLock from 'redis-lock';
|
||||
import { redisClient } from '@/db/redis.js';
|
||||
import { SECOND } from '@/const.js';
|
||||
|
||||
/**
|
||||
* Retry delay (ms) for lock acquisition
|
||||
|
@ -18,14 +19,14 @@ const lock: (key: string, timeout?: number) => Promise<() => void>
|
|||
* @param timeout Lock timeout (ms), The timeout releases previous lock.
|
||||
* @returns Unlock function
|
||||
*/
|
||||
export function getApLock(uri: string, timeout = 30 * 1000) {
|
||||
export function getApLock(uri: string, timeout = 30 * SECOND) {
|
||||
return lock(`ap-object:${uri}`, timeout);
|
||||
}
|
||||
|
||||
export function getFetchInstanceMetadataLock(host: string, timeout = 30 * 1000) {
|
||||
export function getFetchInstanceMetadataLock(host: string, timeout = 30 * SECOND) {
|
||||
return lock(`instance:${host}`, timeout);
|
||||
}
|
||||
|
||||
export function getChartInsertLock(lockKey: string, timeout = 30 * 1000) {
|
||||
export function getChartInsertLock(lockKey: string, timeout = 30 * SECOND) {
|
||||
return lock(`chart-insert:${lockKey}`, timeout);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import chalk from 'chalk';
|
|||
import got, * as Got from 'got';
|
||||
import IPCIDR from 'ip-cidr';
|
||||
import PrivateIp from 'private-ip';
|
||||
import { SECOND, MINUTE } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
import Logger from '@/services/logger.js';
|
||||
import { httpAgent, httpsAgent, StatusError } from './fetch.js';
|
||||
|
@ -16,8 +17,8 @@ export async function downloadUrl(url: string, path: string): Promise<void> {
|
|||
|
||||
logger.info(`Downloading ${chalk.cyan(url)} ...`);
|
||||
|
||||
const timeout = 30 * 1000;
|
||||
const operationTimeout = 60 * 1000;
|
||||
const timeout = 30 * SECOND;
|
||||
const operationTimeout = MINUTE;
|
||||
const maxSize = config.maxFileSize || 262144000;
|
||||
|
||||
const req = got.stream(url, {
|
||||
|
|
|
@ -4,9 +4,10 @@ import { URL } from 'node:url';
|
|||
import CacheableLookup from 'cacheable-lookup';
|
||||
import fetch from 'node-fetch';
|
||||
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
|
||||
import { SECOND } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
|
||||
export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: Record<string, string>) {
|
||||
export async function getJson(url: string, accept = 'application/json, */*', timeout = 10 * SECOND, headers?: Record<string, string>) {
|
||||
const res = await getResponse({
|
||||
url,
|
||||
method: 'GET',
|
||||
|
@ -20,7 +21,7 @@ export async function getJson(url: string, accept = 'application/json, */*', tim
|
|||
return await res.json();
|
||||
}
|
||||
|
||||
export async function getHtml(url: string, accept = 'text/html, */*', timeout = 10000, headers?: Record<string, string>) {
|
||||
export async function getHtml(url: string, accept = 'text/html, */*', timeout = 10 * SECOND, headers?: Record<string, string>) {
|
||||
const res = await getResponse({
|
||||
url,
|
||||
method: 'GET',
|
||||
|
@ -35,7 +36,7 @@ export async function getHtml(url: string, accept = 'text/html, */*', timeout =
|
|||
}
|
||||
|
||||
export async function getResponse(args: { url: string, method: string, body?: string, headers: Record<string, string>, timeout?: number, size?: number }) {
|
||||
const timeout = args.timeout || 10 * 1000;
|
||||
const timeout = args.timeout || 10 * SECOND;
|
||||
|
||||
const controller = new AbortController();
|
||||
setTimeout(() => {
|
||||
|
@ -70,7 +71,7 @@ const cache = new CacheableLookup({
|
|||
*/
|
||||
const _http = new http.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 30 * 1000,
|
||||
keepAliveMsecs: 30 * SECOND,
|
||||
lookup: cache.lookup,
|
||||
} as http.AgentOptions);
|
||||
|
||||
|
@ -79,7 +80,7 @@ const _http = new http.Agent({
|
|||
*/
|
||||
const _https = new https.Agent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 30 * 1000,
|
||||
keepAliveMsecs: 30 * SECOND,
|
||||
lookup: cache.lookup,
|
||||
} as https.AgentOptions);
|
||||
|
||||
|
@ -91,7 +92,7 @@ const maxSockets = Math.max(256, config.deliverJobConcurrency || 128);
|
|||
export const httpAgent = config.proxy
|
||||
? new HttpProxyAgent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 30 * 1000,
|
||||
keepAliveMsecs: 30 * SECOND,
|
||||
maxSockets,
|
||||
maxFreeSockets: 256,
|
||||
scheduling: 'lifo',
|
||||
|
@ -105,7 +106,7 @@ export const httpAgent = config.proxy
|
|||
export const httpsAgent = config.proxy
|
||||
? new HttpsProxyAgent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 30 * 1000,
|
||||
keepAliveMsecs: 30 * SECOND,
|
||||
maxSockets,
|
||||
maxFreeSockets: 256,
|
||||
scheduling: 'lifo',
|
||||
|
|
|
@ -6,6 +6,7 @@ import { DriveFile } from '@/models/entities/drive-file.js';
|
|||
import { Webhook, webhookEventTypes } from '@/models/entities/webhook.js';
|
||||
import { IActivity } from '@/remote/activitypub/type.js';
|
||||
import { envOption } from '@/env.js';
|
||||
import { MINUTE } from '@/const.js';
|
||||
|
||||
import processDeliver from './processors/deliver.js';
|
||||
import processInbox from './processors/inbox.js';
|
||||
|
@ -96,7 +97,7 @@ export function deliver(user: ThinUser, content: unknown, to: string | null) {
|
|||
|
||||
return deliverQueue.add(data, {
|
||||
attempts: config.deliverJobMaxAttempts || 12,
|
||||
timeout: 1 * 60 * 1000, // 1min
|
||||
timeout: MINUTE,
|
||||
backoff: {
|
||||
type: 'apBackoff',
|
||||
},
|
||||
|
@ -113,7 +114,7 @@ export function inbox(activity: IActivity, signature: httpSignature.IParsedSigna
|
|||
|
||||
return inboxQueue.add(data, {
|
||||
attempts: config.inboxJobMaxAttempts || 8,
|
||||
timeout: 5 * 60 * 1000, // 5min
|
||||
timeout: 5 * MINUTE,
|
||||
backoff: {
|
||||
type: 'apBackoff',
|
||||
},
|
||||
|
@ -278,7 +279,7 @@ export function webhookDeliver(webhook: Webhook, type: typeof webhookEventTypes[
|
|||
|
||||
return webhookDeliverQueue.add(data, {
|
||||
attempts: 4,
|
||||
timeout: 1 * 60 * 1000, // 1min
|
||||
timeout: MINUTE,
|
||||
backoff: {
|
||||
type: 'apBackoff',
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Bull from 'bull';
|
||||
import { SECOND, MINUTE, HOUR } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
import { getRedisOptions } from '@/config/redis.js';
|
||||
|
||||
|
@ -8,7 +9,7 @@ export function initialize<T>(name: string, limitPerSec = -1): Bull.Queue<T> {
|
|||
prefix: config.redis.prefix ? `${config.redis.prefix}:queue` : 'queue',
|
||||
limiter: limitPerSec > 0 ? {
|
||||
max: limitPerSec,
|
||||
duration: 1000,
|
||||
duration: SECOND,
|
||||
} : undefined,
|
||||
settings: {
|
||||
backoffStrategies: {
|
||||
|
@ -20,8 +21,8 @@ export function initialize<T>(name: string, limitPerSec = -1): Bull.Queue<T> {
|
|||
|
||||
// ref. https://github.com/misskey-dev/misskey/pull/7635#issue-971097019
|
||||
function apBackoff(attemptsMade: number, err: Error) {
|
||||
const baseDelay = 60 * 1000; // 1min
|
||||
const maxBackoff = 8 * 60 * 60 * 1000; // 8hours
|
||||
const baseDelay = MINUTE;
|
||||
const maxBackoff = 8 * HOUR;
|
||||
let backoff = (Math.pow(2, attemptsMade) - 1) * baseDelay;
|
||||
backoff = Math.min(backoff, maxBackoff);
|
||||
backoff += Math.round(backoff * Math.random() * 0.2);
|
||||
|
|
|
@ -3,6 +3,7 @@ import Bull from 'bull';
|
|||
import { format as dateFormat } from 'date-fns';
|
||||
import { In, MoreThan, Not } from 'typeorm';
|
||||
|
||||
import { MONTH } from '@/const.js';
|
||||
import { getFullApAccount } from '@/misc/convert-host.js';
|
||||
import { createTemp } from '@/misc/create-temp.js';
|
||||
import { Following } from '@/models/entities/following.js';
|
||||
|
@ -61,7 +62,7 @@ export async function exportFollowing(job: Bull.Job<DbUserJobData>, done: () =>
|
|||
continue;
|
||||
}
|
||||
|
||||
if (job.data.excludeInactive && u.updatedAt && (Date.now() - u.updatedAt.getTime() > 1000 * 60 * 60 * 24 * 90)) {
|
||||
if (job.data.excludeInactive && u.updatedAt && (Date.now() - u.updatedAt.getTime() > 3 * MONTH)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { CacheableRemoteUser } from '@/models/entities/user.js';
|
||||
import { IObject } from './type.js';
|
||||
import { performActivity } from './kernel/index.js';
|
||||
|
@ -6,9 +7,9 @@ import { updatePerson } from './models/person.js';
|
|||
export default async (actor: CacheableRemoteUser, activity: IObject): Promise<void> => {
|
||||
await performActivity(actor, activity);
|
||||
|
||||
// ついでにリモートユーザーの情報が古かったら更新しておく
|
||||
// And while I'm at it, I'll update the remote user information if it's out of date.
|
||||
if (actor.uri) {
|
||||
if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
|
||||
if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > DAY) {
|
||||
setImmediate(() => {
|
||||
updatePerson(actor.uri!);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { URL } from 'node:url';
|
||||
import chalk from 'chalk';
|
||||
import { IsNull } from 'typeorm';
|
||||
import { DAY } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
import { isSelfHost, toPuny } from '@/misc/convert-host.js';
|
||||
import { User, IRemoteUser } from '@/models/entities/user.js';
|
||||
|
@ -49,9 +50,9 @@ export async function resolveUser(username: string, idnHost: string | null): Pro
|
|||
return await createPerson(self.href);
|
||||
}
|
||||
|
||||
// ユーザー情報が古い場合は、WebFilgerからやりなおして返す
|
||||
if (user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
|
||||
// 繋がらないインスタンスに何回も試行するのを防ぐ, 後続の同様処理の連続試行を防ぐ ため 試行前にも更新する
|
||||
// If user information is out of date, start over with webfinger
|
||||
if (user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > DAY) {
|
||||
// Prevent race conditions
|
||||
await Users.update(user.id, {
|
||||
lastFetchedAt: new Date(),
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import rndstr from 'rndstr';
|
||||
import { DAY } from '@/const.js';
|
||||
import { Note } from '@/models/entities/note.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import { Notes, UserProfiles, NoteReactions } from '@/models/index.js';
|
||||
|
@ -16,13 +17,13 @@ export async function injectFeatured(timeline: Note[], user?: User | null) {
|
|||
}
|
||||
|
||||
const max = 30;
|
||||
const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
|
||||
const offset = 3 * DAY;
|
||||
|
||||
const query = Notes.createQueryBuilder('note')
|
||||
.addSelect('note.score')
|
||||
.where('note.userHost IS NULL')
|
||||
.andWhere('note.score > 0')
|
||||
.andWhere('note.createdAt > :date', { date: new Date(Date.now() - day) })
|
||||
.andWhere('note.createdAt > :date', { date: new Date(Date.now() - offset) })
|
||||
.andWhere("note.visibility = 'public'")
|
||||
.innerJoinAndSelect('note.user', 'user');
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { Users } from '@/models/index.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
|
@ -46,7 +47,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
case 'admin': query.where('user.isAdmin = TRUE'); break;
|
||||
case 'moderator': query.where('user.isModerator = TRUE'); break;
|
||||
case 'adminOrModerator': query.where('user.isAdmin = TRUE OR user.isModerator = TRUE'); break;
|
||||
case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
|
||||
case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 5 * DAY) }); break;
|
||||
case 'silenced': query.where('user.isSilenced = TRUE'); break;
|
||||
case 'suspended': query.where('user.isSuspended = TRUE'); break;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { GalleryPosts } from '@/models/index.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
|
@ -26,7 +27,7 @@ export const paramDef = {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, me) => {
|
||||
const query = GalleryPosts.createQueryBuilder('post')
|
||||
.andWhere('post.createdAt > :date', { date: new Date(Date.now() - (1000 * 60 * 60 * 24 * 3)) })
|
||||
.andWhere('post.createdAt > :date', { date: new Date(Date.now() - 3 * DAY) })
|
||||
.andWhere('post.likedCount > 0')
|
||||
.orderBy('post.likedCount', 'DESC');
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Brackets } from 'typeorm';
|
||||
import { MINUTE, HOUR } from '@/const.js';
|
||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { Notes } from '@/models/index.js';
|
||||
import { Note } from '@/models/entities/note.js';
|
||||
|
@ -13,8 +14,8 @@ import define from '../../define.js';
|
|||
..が理想だけどPostgreSQLでどうするのか分からないので単に「直近Aの内に投稿されたユニーク投稿数が多いハッシュタグ」で妥協する
|
||||
*/
|
||||
|
||||
const rangeA = 1000 * 60 * 60; // 60分
|
||||
//const rangeB = 1000 * 60 * 120; // 2時間
|
||||
const rangeA = HOUR;
|
||||
//const rangeB = 2 * HOUR;
|
||||
//const coefficient = 1.25; // 「n倍」の部分
|
||||
//const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
|
||||
|
||||
|
@ -116,8 +117,7 @@ export default define(meta, paramDef, async () => {
|
|||
|
||||
const range = 20;
|
||||
|
||||
// 10分
|
||||
const interval = 1000 * 60 * 10;
|
||||
const interval = 10 * MINUTE;
|
||||
|
||||
for (let i = 0; i < range; i++) {
|
||||
countPromises.push(Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { Users } from '@/models/index.js';
|
||||
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
|
||||
import define from '../../define.js';
|
||||
|
@ -35,7 +36,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const query = Users.createQueryBuilder('user')
|
||||
.where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) });
|
||||
|
||||
const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5));
|
||||
const recent = new Date(Date.now() - 5 * DAY);
|
||||
|
||||
if (ps.state === 'alive') {
|
||||
query.andWhere('user.updatedAt > :date', { date: recent });
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { promisify } from 'node:util';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import * as cbor from 'cbor';
|
||||
import { MINUTE } from '@/const.js';
|
||||
import {
|
||||
UserProfiles,
|
||||
UserSecurityKeys,
|
||||
|
@ -112,10 +113,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
id: ps.challengeId,
|
||||
});
|
||||
|
||||
// Expired challenge (> 5min old)
|
||||
// Expired challenge
|
||||
if (
|
||||
new Date().getTime() - attestationChallenge.createdAt.getTime() >=
|
||||
5 * 60 * 1000
|
||||
5 * MINUTE
|
||||
) {
|
||||
throw new Error('expired challenge');
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { Notes } from '@/models/index.js';
|
||||
import define from '../../define.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
|
@ -31,7 +32,7 @@ export const paramDef = {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
const max = 30;
|
||||
const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
|
||||
const day = 3 * DAY;
|
||||
|
||||
const query = Notes.createQueryBuilder('note')
|
||||
.addSelect('note.score')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { DAY } from '@/const.js';
|
||||
import { Users } from '@/models/index.js';
|
||||
import define from '../define.js';
|
||||
import { generateMutedUserQueryForUsers } from '../common/generate-muted-user-query.js';
|
||||
|
@ -46,7 +47,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
case 'admin': query.andWhere('user.isAdmin = TRUE'); break;
|
||||
case 'moderator': query.andWhere('user.isModerator = TRUE'); break;
|
||||
case 'adminOrModerator': query.andWhere('user.isAdmin = TRUE OR user.isModerator = TRUE'); break;
|
||||
case 'alive': query.andWhere('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
|
||||
case 'alive': query.andWhere('user.updatedAt > :date', { date: new Date(Date.now() - 5 * DAY) }); break;
|
||||
}
|
||||
|
||||
switch (ps.origin) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { MONTH } from '@/const.js';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { Followings, Users } from '@/models/index.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
|
@ -39,7 +40,7 @@ export const paramDef = {
|
|||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, me) => {
|
||||
const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
|
||||
const activeThreshold = new Date(Date.now() - MONTH);
|
||||
|
||||
if (ps.host) {
|
||||
const q = Users.createQueryBuilder('user')
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Brackets } from 'typeorm';
|
||||
import { MONTH } from '@/const.js';
|
||||
import { UserProfiles, Users } from '@/models/index.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import define from '../../define.js';
|
||||
|
@ -35,7 +36,7 @@ export const paramDef = {
|
|||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, me) => {
|
||||
const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
|
||||
const activeThreshold = new Date(Date.now() - MONTH);
|
||||
|
||||
const isUsername = ps.query.startsWith('@');
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { IsNull } from 'typeorm';
|
|||
import Koa from 'koa';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import { SECOND, MINUTE, HOUR } from '@/const.js';
|
||||
import config from '@/config/index.js';
|
||||
import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '@/models/index.js';
|
||||
import { ILocalUser } from '@/models/entities/user.js';
|
||||
|
@ -38,7 +39,7 @@ export default async (ctx: Koa.Context) => {
|
|||
|
||||
try {
|
||||
// not more than 1 attempt per second and not more than 10 attempts per hour
|
||||
await limiter({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(ctx.ip));
|
||||
await limiter({ key: 'signin', duration: HOUR, max: 10, minInterval: SECOND }, getIpHash(ctx.ip));
|
||||
} catch (err) {
|
||||
error(new ApiError('RATE_LIMIT_EXCEEDED'));
|
||||
return;
|
||||
|
@ -149,7 +150,7 @@ export default async (ctx: Koa.Context) => {
|
|||
id: body.challengeId,
|
||||
});
|
||||
|
||||
if (new Date().getTime() - challenge.createdAt.getTime() >= 5 * 60 * 1000) {
|
||||
if (new Date().getTime() - challenge.createdAt.getTime() >= 5 * MINUTE) {
|
||||
await fail();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import { WEEK, MONTH, YEAR } from '@/const.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import Chart, { KVs } from '../core.js';
|
||||
import { name, schema } from './entities/active-users.js';
|
||||
|
||||
const week = 1000 * 60 * 60 * 24 * 7;
|
||||
const month = 1000 * 60 * 60 * 24 * 30;
|
||||
const year = 1000 * 60 * 60 * 24 * 365;
|
||||
|
||||
/**
|
||||
* アクティブユーザーに関するチャート
|
||||
* Chart on Active Users
|
||||
*/
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default class ActiveUsersChart extends Chart<typeof schema> {
|
||||
|
@ -26,12 +23,12 @@ export default class ActiveUsersChart extends Chart<typeof schema> {
|
|||
public async read(user: { id: User['id'], host: null, createdAt: User['createdAt'] }): Promise<void> {
|
||||
await this.commit({
|
||||
'read': [user.id],
|
||||
'registeredWithinWeek': (Date.now() - user.createdAt.getTime() < week) ? [user.id] : [],
|
||||
'registeredWithinMonth': (Date.now() - user.createdAt.getTime() < month) ? [user.id] : [],
|
||||
'registeredWithinYear': (Date.now() - user.createdAt.getTime() < year) ? [user.id] : [],
|
||||
'registeredOutsideWeek': (Date.now() - user.createdAt.getTime() > week) ? [user.id] : [],
|
||||
'registeredOutsideMonth': (Date.now() - user.createdAt.getTime() > month) ? [user.id] : [],
|
||||
'registeredOutsideYear': (Date.now() - user.createdAt.getTime() > year) ? [user.id] : [],
|
||||
'registeredWithinWeek': (Date.now() - user.createdAt.getTime() < WEEK) ? [user.id] : [],
|
||||
'registeredWithinMonth': (Date.now() - user.createdAt.getTime() < MONTH) ? [user.id] : [],
|
||||
'registeredWithinYear': (Date.now() - user.createdAt.getTime() < YEAR) ? [user.id] : [],
|
||||
'registeredOutsideWeek': (Date.now() - user.createdAt.getTime() > WEEK) ? [user.id] : [],
|
||||
'registeredOutsideMonth': (Date.now() - user.createdAt.getTime() > MONTH) ? [user.id] : [],
|
||||
'registeredOutsideYear': (Date.now() - user.createdAt.getTime() > YEAR) ? [user.id] : [],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { MONTH } from '@/const.js';
|
||||
import { Followings, Instances } from '@/models/index.js';
|
||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import Chart, { KVs } from '../core.js';
|
||||
|
@ -65,7 +66,7 @@ export default class FederationChart extends Chart<typeof schema> {
|
|||
.where(`instance.host IN (${ subInstancesQuery.getQuery() })`)
|
||||
.andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT IN (:...blocked)', { blocked: meta.blockedHosts })
|
||||
.andWhere('instance.isSuspended = false')
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) })
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - MONTH) })
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10)),
|
||||
Instances.createQueryBuilder('instance')
|
||||
|
@ -73,7 +74,7 @@ export default class FederationChart extends Chart<typeof schema> {
|
|||
.where(`instance.host IN (${ pubInstancesQuery.getQuery() })`)
|
||||
.andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT IN (:...blocked)', { blocked: meta.blockedHosts })
|
||||
.andWhere('instance.isSuspended = false')
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) })
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - MONTH) })
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10)),
|
||||
]);
|
||||
|
|
|
@ -2,6 +2,7 @@ import { URL } from 'node:url';
|
|||
import { DOMWindow, JSDOM } from 'jsdom';
|
||||
import fetch from 'node-fetch';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { DAY } from '@/const.js';
|
||||
import { getJson, getHtml, getAgentByUrl } from '@/misc/fetch.js';
|
||||
import { Instance } from '@/models/entities/instance.js';
|
||||
import { Instances } from '@/models/index.js';
|
||||
|
@ -16,7 +17,7 @@ export async function fetchInstanceMetadata(instance: Instance, force = false):
|
|||
if (!force) {
|
||||
const _instance = await Instances.findOneBy({ host: instance.host });
|
||||
const now = Date.now();
|
||||
if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
|
||||
if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < DAY)) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue