Save the maximum package name length which was seen

This commit is contained in:
Jonas Lochmann 2020-10-05 02:00:00 +02:00
parent b4fd177afe
commit ba3bb50113
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
5 changed files with 79 additions and 15 deletions

View file

@ -14,8 +14,8 @@ Use this to get the server status.
## Response
This returns a JSON object with ``websocketClients`` (of the type number,
the number of clients connected using the websocket) and the map ``counters``
which maps values to numbers. You should not make any assumptions about the counter names
the number of clients connected using the websocket) and the maps ``counters`` and ``maxValues``
which map values to numbers. You should not make any assumptions about the key names
and their availability.
### example response
@ -25,13 +25,16 @@ and their availability.
"websocketClients": 3,
"counters": {
"testCounter": 1
},
"maxValues": {
"testMax": 3
}
}
```
## 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

View file

@ -34,9 +34,12 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
router.get('/status', async (_, res, next) => {
try {
const { counters, maxValues } = await eventHandler.getValues()
res.json({
websocketClients: websocket.countConnections(),
counters: await eventHandler.getCounters()
counters,
maxValues
})
} catch (ex) {
next(ex)
@ -45,7 +48,7 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
router.post('/reset-counters', async (_, res, next) => {
try {
await eventHandler.resetCounters()
await eventHandler.reset()
res.json({ ok: true })
} catch (ex) {

View file

@ -15,6 +15,8 @@
* 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 { ClientPushChangesRequestAction } from '../../../../api/schema'
import { isSerializedAppLogicAction } from '../../../../api/validator'
@ -23,6 +25,30 @@ import { Cache } from '../cache'
import { dispatchAppLogicAction as dispatchAppLogicActionInternal } from '../dispatch-app-logic-action'
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 }: {
action: ClientPushChangesRequestAction
deviceId: string
@ -36,6 +62,11 @@ export async function dispatchAppLogicAction ({ action, eventHandler, deviceId,
validator: isSerializedAppLogicAction,
parser: parseAppLogicAction,
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 })
}
})

View file

@ -17,6 +17,10 @@
export interface EventHandler {
countEvent (name: string): void
getCounters (): Promise<{[key: string]: number}>
resetCounters (): Promise<void>
reportMax (name: string, value: number): void
getValues (): Promise<{
counters: {[key: string]: number}
maxValues: {[key: string]: number}
}>
reset (): Promise<void>
}

View file

@ -19,6 +19,7 @@ import { EventHandler } from './eventhandler'
export class InMemoryEventHandler implements EventHandler {
private counters = new Map<string, number>()
private maxValues = new Map<string, number>()
countEvent (name: string) {
this.counters.set(
@ -27,17 +28,39 @@ export class InMemoryEventHandler implements EventHandler {
)
}
async getCounters () {
const result: {[key: string]: number} = {}
reportMax (name: string, value: number) {
this.maxValues.set(
name,
Math.max((this.maxValues.get(name) || 0), value)
)
}
this.counters.forEach((value, key) => {
async getValues () {
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
}
async resetCounters () {
this.counters.clear()
}
}