mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2025-10-03 09:49:32 +02:00
Save the maximum package name length which was seen
This commit is contained in:
parent
b4fd177afe
commit
ba3bb50113
5 changed files with 79 additions and 15 deletions
|
@ -14,8 +14,8 @@ Use this to get the server status.
|
||||||
## Response
|
## Response
|
||||||
|
|
||||||
This returns a JSON object with ``websocketClients`` (of the type number,
|
This returns a JSON object with ``websocketClients`` (of the type number,
|
||||||
the number of clients connected using the websocket) and the map ``counters``
|
the number of clients connected using the websocket) and the maps ``counters`` and ``maxValues``
|
||||||
which maps values to numbers. You should not make any assumptions about the counter names
|
which map values to numbers. You should not make any assumptions about the key names
|
||||||
and their availability.
|
and their availability.
|
||||||
|
|
||||||
### example response
|
### example response
|
||||||
|
@ -25,13 +25,16 @@ and their availability.
|
||||||
"websocketClients": 3,
|
"websocketClients": 3,
|
||||||
"counters": {
|
"counters": {
|
||||||
"testCounter": 1
|
"testCounter": 1
|
||||||
|
},
|
||||||
|
"maxValues": {
|
||||||
|
"testMax": 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## POST /admin/reset-counters
|
## POST /admin/reset-counters
|
||||||
|
|
||||||
Use this to reset the counters included in the server status.
|
Use this to reset the counters and maxValues included in the server status.
|
||||||
|
|
||||||
Although this uses POST, it does not take any request body
|
Although this uses POST, it does not take any request body
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,12 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
|
||||||
|
|
||||||
router.get('/status', async (_, res, next) => {
|
router.get('/status', async (_, res, next) => {
|
||||||
try {
|
try {
|
||||||
|
const { counters, maxValues } = await eventHandler.getValues()
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
websocketClients: websocket.countConnections(),
|
websocketClients: websocket.countConnections(),
|
||||||
counters: await eventHandler.getCounters()
|
counters,
|
||||||
|
maxValues
|
||||||
})
|
})
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
next(ex)
|
next(ex)
|
||||||
|
@ -45,7 +48,7 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
|
||||||
|
|
||||||
router.post('/reset-counters', async (_, res, next) => {
|
router.post('/reset-counters', async (_, res, next) => {
|
||||||
try {
|
try {
|
||||||
await eventHandler.resetCounters()
|
await eventHandler.reset()
|
||||||
|
|
||||||
res.json({ ok: true })
|
res.json({ ok: true })
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { max } from 'lodash'
|
||||||
|
import { AddInstalledAppsAction, AppLogicAction, UpdateAppActivitiesAction } from '../../../../action'
|
||||||
import { parseAppLogicAction } from '../../../../action/serialization'
|
import { parseAppLogicAction } from '../../../../action/serialization'
|
||||||
import { ClientPushChangesRequestAction } from '../../../../api/schema'
|
import { ClientPushChangesRequestAction } from '../../../../api/schema'
|
||||||
import { isSerializedAppLogicAction } from '../../../../api/validator'
|
import { isSerializedAppLogicAction } from '../../../../api/validator'
|
||||||
|
@ -23,6 +25,30 @@ import { Cache } from '../cache'
|
||||||
import { dispatchAppLogicAction as dispatchAppLogicActionInternal } from '../dispatch-app-logic-action'
|
import { dispatchAppLogicAction as dispatchAppLogicActionInternal } from '../dispatch-app-logic-action'
|
||||||
import { dispatch } from './helper'
|
import { dispatch } from './helper'
|
||||||
|
|
||||||
|
function getAppRelatedMaxValues (action: AppLogicAction): {
|
||||||
|
packageNameLength: number | null
|
||||||
|
activityNameLength: number | null
|
||||||
|
} {
|
||||||
|
if (action instanceof AddInstalledAppsAction) {
|
||||||
|
const packageNameLength = max(action.apps.map((item) => item.packageName.length)) || null
|
||||||
|
|
||||||
|
return { packageNameLength, activityNameLength: null }
|
||||||
|
} else if (action instanceof UpdateAppActivitiesAction) {
|
||||||
|
const packageNameLength = max(action.updatedOrAdded.map((item) => item.packageName.length)) || null
|
||||||
|
const activityNameLength = max(action.updatedOrAdded.map((item) => item.activityName.length)) || null
|
||||||
|
|
||||||
|
return { packageNameLength, activityNameLength }
|
||||||
|
} else return { packageNameLength: null, activityNameLength: null }
|
||||||
|
}
|
||||||
|
|
||||||
|
function roundCounterUp (input: number, factor: number) {
|
||||||
|
if (input % factor === 0) {
|
||||||
|
return input
|
||||||
|
} else {
|
||||||
|
return input - (input % factor) + factor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function dispatchAppLogicAction ({ action, eventHandler, deviceId, cache }: {
|
export async function dispatchAppLogicAction ({ action, eventHandler, deviceId, cache }: {
|
||||||
action: ClientPushChangesRequestAction
|
action: ClientPushChangesRequestAction
|
||||||
deviceId: string
|
deviceId: string
|
||||||
|
@ -36,6 +62,11 @@ export async function dispatchAppLogicAction ({ action, eventHandler, deviceId,
|
||||||
validator: isSerializedAppLogicAction,
|
validator: isSerializedAppLogicAction,
|
||||||
parser: parseAppLogicAction,
|
parser: parseAppLogicAction,
|
||||||
applier: async (action) => {
|
applier: async (action) => {
|
||||||
|
const maxValues = getAppRelatedMaxValues(action)
|
||||||
|
|
||||||
|
if (maxValues.packageNameLength) eventHandler.reportMax('packageNameLength', roundCounterUp(maxValues.packageNameLength, 10))
|
||||||
|
if (maxValues.activityNameLength) eventHandler.reportMax('activityNameLength', roundCounterUp(maxValues.activityNameLength, 10))
|
||||||
|
|
||||||
await dispatchAppLogicActionInternal({ action, cache, eventHandler, deviceId })
|
await dispatchAppLogicActionInternal({ action, cache, eventHandler, deviceId })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
|
|
||||||
export interface EventHandler {
|
export interface EventHandler {
|
||||||
countEvent (name: string): void
|
countEvent (name: string): void
|
||||||
getCounters (): Promise<{[key: string]: number}>
|
reportMax (name: string, value: number): void
|
||||||
resetCounters (): Promise<void>
|
getValues (): Promise<{
|
||||||
|
counters: {[key: string]: number}
|
||||||
|
maxValues: {[key: string]: number}
|
||||||
|
}>
|
||||||
|
reset (): Promise<void>
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { EventHandler } from './eventhandler'
|
||||||
|
|
||||||
export class InMemoryEventHandler implements EventHandler {
|
export class InMemoryEventHandler implements EventHandler {
|
||||||
private counters = new Map<string, number>()
|
private counters = new Map<string, number>()
|
||||||
|
private maxValues = new Map<string, number>()
|
||||||
|
|
||||||
countEvent (name: string) {
|
countEvent (name: string) {
|
||||||
this.counters.set(
|
this.counters.set(
|
||||||
|
@ -27,17 +28,39 @@ export class InMemoryEventHandler implements EventHandler {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCounters () {
|
reportMax (name: string, value: number) {
|
||||||
const result: {[key: string]: number} = {}
|
this.maxValues.set(
|
||||||
|
name,
|
||||||
|
Math.max((this.maxValues.get(name) || 0), value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
this.counters.forEach((value, key) => {
|
async getValues () {
|
||||||
result[key] = value
|
return {
|
||||||
|
counters: this.buildObject(this.counters),
|
||||||
|
maxValues: this.buildObject(this.maxValues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async reset () {
|
||||||
|
this.counters.clear()
|
||||||
|
this.maxValues.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildObject<T> (map: Map<string, T>): {[key: string]: T} {
|
||||||
|
const result: {[key: string]: T} = {}
|
||||||
|
|
||||||
|
const keys: Array<string> = []
|
||||||
|
map.forEach((_, key) => keys.push(key))
|
||||||
|
|
||||||
|
keys.sort().forEach((key) => {
|
||||||
|
const value = map.get(key)
|
||||||
|
|
||||||
|
if (value !== undefined) {
|
||||||
|
result[key] = value
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async resetCounters () {
|
|
||||||
this.counters.clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue