UBERF-7705: Maitenance warning for every transactor (#6169)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-07-29 18:06:31 +07:00 committed by GitHub
parent 9fb19e3e26
commit 144d9a1a80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 81 additions and 4 deletions

View File

@ -3,7 +3,7 @@
import login from '@hcengineering/login' import login from '@hcengineering/login'
import { getEmbeddedLabel, getMetadata } from '@hcengineering/platform' import { getEmbeddedLabel, getMetadata } from '@hcengineering/platform'
import presentation, { getClient, isAdminUser } from '@hcengineering/presentation' import presentation, { getClient, isAdminUser } from '@hcengineering/presentation'
import { Button, IconArrowRight, fetchMetadataLocalStorage } from '@hcengineering/ui' import { Button, IconArrowLeft, IconArrowRight, fetchMetadataLocalStorage } from '@hcengineering/ui'
import EditBox from '@hcengineering/ui/src/components/EditBox.svelte' import EditBox from '@hcengineering/ui/src/components/EditBox.svelte'
const _endpoint: string = fetchMetadataLocalStorage(login.metadata.LoginEndpoint) ?? '' const _endpoint: string = fetchMetadataLocalStorage(login.metadata.LoginEndpoint) ?? ''
@ -107,9 +107,12 @@
icon={IconArrowRight} icon={IconArrowRight}
label={getEmbeddedLabel('Set maintenance warning')} label={getEmbeddedLabel('Set maintenance warning')}
on:click={() => { on:click={() => {
const endpoint = getMetadata(login.metadata.AccountsUrl) ?? ''
if (endpoint !== '') {
void fetch(endpoint + `/api/v1/manage?token=${token}&operation=maintenance&timeout=${warningTimeout}`, { void fetch(endpoint + `/api/v1/manage?token=${token}&operation=maintenance&timeout=${warningTimeout}`, {
method: 'PUT' method: 'PUT'
}) })
}
}} }}
/> />
<div class="flex-col p-1"> <div class="flex-col p-1">
@ -117,6 +120,18 @@
<EditBox kind={'underline'} format={'number'} bind:value={warningTimeout} /> min <EditBox kind={'underline'} format={'number'} bind:value={warningTimeout} /> min
</div> </div>
</div> </div>
<Button
icon={IconArrowLeft}
label={getEmbeddedLabel('Clear warning')}
on:click={() => {
const endpoint = getMetadata(login.metadata.AccountsUrl) ?? ''
if (endpoint !== '') {
void fetch(endpoint + `/api/v1/manage?token=${token}&operation=maintenance&timeout=-1`, {
method: 'PUT'
})
}
}}
/>
</div> </div>
<div class="flex-col p-1"> <div class="flex-col p-1">
<div class="flex-row-center p-1"> <div class="flex-row-center p-1">

View File

@ -4,9 +4,11 @@
import account, { import account, {
ACCOUNT_DB, ACCOUNT_DB,
EndpointKind,
UpgradeWorker, UpgradeWorker,
accountId, accountId,
cleanInProgressWorkspaces, cleanInProgressWorkspaces,
getAllTransactors,
getMethods getMethods
} from '@hcengineering/account' } from '@hcengineering/account'
import accountEn from '@hcengineering/account/lang/en.json' import accountEn from '@hcengineering/account/lang/en.json'
@ -166,6 +168,44 @@ export function serveAccount (
} }
}) })
router.put('/api/v1/manage', async (req, res) => {
try {
const token = req.query.token as string
const payload = decodeToken(token)
if (payload.extra?.admin !== 'true') {
req.res.writeHead(404, {})
req.res.end()
return
}
const operation = req.query.operation
switch (operation) {
case 'maintenance': {
const timeMinutes = parseInt((req.query.timeout as string) ?? '5')
const transactors = getAllTransactors(EndpointKind.Internal)
for (const tr of transactors) {
const serverEndpoint = tr.replaceAll('wss://', 'https://').replace('ws://', 'http://')
await fetch(serverEndpoint + `/api/v1/manage?token=${token}&operation=maintenance&timeout=${timeMinutes}`, {
method: 'PUT'
})
}
req.res.writeHead(200)
req.res.end()
return
}
}
req.res.writeHead(404, {})
req.res.end()
} catch (err: any) {
Analytics.handleError(err)
req.res.writeHead(404, {})
req.res.end()
}
})
router.post('rpc', '/', async (ctx) => { router.post('rpc', '/', async (ctx) => {
const token = extractToken(ctx.request.headers) const token = extractToken(ctx.request.headers)

View File

@ -148,6 +148,28 @@ const getEndpoint = (ctx: MeasureContext, workspaceInfo: Workspace, kind: Endpoi
return transactors[Math.abs(hash % transactors.length)] return transactors[Math.abs(hash % transactors.length)]
} }
export function getAllTransactors (kind: EndpointKind): string[] {
const transactorsUrl = getMetadata(accountPlugin.metadata.Transactors)
if (transactorsUrl === undefined) {
throw new Error('Please provide transactor endpoint url')
}
const endpoints = transactorsUrl
.split(',')
.map((it) => it.trim())
.filter((it) => it.length > 0)
if (endpoints.length === 0) {
throw new Error('Please provide transactor endpoint url')
}
const toTransactor = (line: string): { internalUrl: string, group: string, externalUrl: string } => {
const [internalUrl, externalUrl, group] = line.split(';')
return { internalUrl, group: group ?? '', externalUrl: externalUrl ?? internalUrl }
}
return endpoints.map(toTransactor).map((it) => (kind === EndpointKind.External ? it.externalUrl : it.internalUrl))
}
/** /**
* @public * @public
*/ */