TSK-1065: Check model version (#2916)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2023-04-07 12:18:07 +07:00 committed by GitHub
parent 33db59a5e2
commit b699096e22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 22 deletions

View File

@ -337,6 +337,13 @@ export interface Version extends Doc {
patch: number
}
/**
* @public
*/
export function versionToString (version: Version): string {
return `${version?.major}.${version?.minor}.${version?.patch}`
}
/**
* Blob data from s3 storage
* @public

View File

@ -15,8 +15,7 @@
import { Plugin } from '@hcengineering/platform'
import { BackupClient, DocChunk } from './backup'
import type { Class, Doc, Domain, PluginConfiguration, Ref } from './classes'
import { DOMAIN_MODEL } from './classes'
import { Class, DOMAIN_MODEL, Doc, Domain, PluginConfiguration, Ref } from './classes'
import core from './component'
import { Hierarchy } from './hierarchy'
import { ModelDb } from './memdb'
@ -52,7 +51,7 @@ export interface Client extends Storage {
*/
export interface ClientConnection extends Storage, BackupClient {
close: () => Promise<void>
onConnect?: () => Promise<void>
onConnect?: (apply: boolean) => Promise<void>
}
class ClientImpl implements Client, BackupClient {
@ -189,7 +188,7 @@ export async function createClient (
}
txBuffer = undefined
const oldOnConnect: (() => void) | undefined = conn.onConnect
const oldOnConnect: ((apply: boolean) => void) | undefined = conn.onConnect
conn.onConnect = async () => {
// Find all new transactions and apply
await loadModel(conn, loadedTxIds, allowedPlugins, configs, hierarchy, model)
@ -205,9 +204,10 @@ export async function createClient (
for (const tx of atxes) {
txHandler(tx)
}
await oldOnConnect?.(true)
} else {
// We need to trigger full refresh on queries, etc.
await oldOnConnect?.()
await oldOnConnect?.(false)
}
}

View File

@ -73,7 +73,7 @@ class Connection implements ClientConnection {
private readonly handler: TxHandler,
private readonly onUpgrade?: () => void,
private readonly onUnauthorized?: () => void,
readonly onConnect?: () => Promise<void>
readonly onConnect?: (apply: boolean) => Promise<void>
) {
console.log('connection created')
this.interval = setInterval(() => {
@ -151,7 +151,7 @@ class Connection implements ClientConnection {
v.reconnect?.()
}
resolve(websocket)
void this.onConnect?.()
void this.onConnect?.(false)
return
}
@ -307,9 +307,9 @@ export async function connect (
handler: TxHandler,
onUpgrade?: () => void,
onUnauthorized?: () => void,
onConnect?: () => void
onConnect?: (apply: boolean) => void
): Promise<ClientConnection> {
return new Connection(url, handler, onUpgrade, onUnauthorized, async () => {
onConnect?.()
return new Connection(url, handler, onUpgrade, onUnauthorized, async (apply) => {
onConnect?.(apply)
})
}

View File

@ -14,7 +14,7 @@
//
import clientPlugin from '@hcengineering/client'
import { Client, createClient, TxHandler } from '@hcengineering/core'
import core, { Client, createClient, TxHandler, TxWorkspaceEvent, WorkspaceEvent } from '@hcengineering/core'
import { getMetadata, getPlugins, getResource } from '@hcengineering/platform'
import { connect } from './connection'
@ -29,7 +29,7 @@ export default async () => {
endpoint: string,
onUpgrade?: () => void,
onUnauthorized?: () => void,
onConnect?: () => void
onConnect?: (apply: boolean) => void
): Promise<Client> => {
const filterModel = getMetadata(clientPlugin.metadata.FilterModel) ?? false
@ -37,7 +37,16 @@ export default async () => {
(handler: TxHandler) => {
const url = new URL(`/${token}`, endpoint)
console.log('connecting to', url.href)
return connect(url.href, handler, onUpgrade, onUnauthorized, onConnect)
const upgradeHandler: TxHandler = (tx) => {
if (tx._class === core.class.TxWorkspaceEvent) {
if ((tx as TxWorkspaceEvent).event === WorkspaceEvent.Upgrade) {
onUpgrade?.()
}
}
handler(tx)
}
return connect(url.href, upgradeHandler, onUpgrade, onUnauthorized, onConnect)
},
filterModel ? getPlugins() : undefined
)

View File

@ -57,7 +57,7 @@ export type ClientFactory = (
endpoint: string,
onUpgrade?: () => void,
onUnauthorized?: () => void,
onConnect?: () => void
onConnect?: (apply: boolean) => void
) => Promise<Client>
export default plugin(clientId, {

View File

@ -1,6 +1,6 @@
import client from '@hcengineering/client'
import contact from '@hcengineering/contact'
import core, { Client, setCurrentAccount, Version } from '@hcengineering/core'
import core, { Client, setCurrentAccount, Version, versionToString } from '@hcengineering/core'
import login, { loginId } from '@hcengineering/login'
import { getMetadata, getResource, setMetadata } from '@hcengineering/platform'
import presentation, { refreshClient, setClient } from '@hcengineering/presentation'
@ -41,6 +41,8 @@ export async function connect (title: string): Promise<Client | undefined> {
let clientSet = false
let version: Version | undefined
const clientFactory = await getResource(client.function.GetClient)
_client = await clientFactory(
token,
@ -56,11 +58,24 @@ export async function connect (title: string): Promise<Client | undefined> {
})
},
// We need to refresh all active live queries and clear old queries.
() => {
(apply: boolean) => {
try {
if (clientSet) {
if (clientSet && !apply) {
void refreshClient()
}
void (async () => {
const newVersion = await _client?.findOne<Version>(core.class.Version, {})
console.log('Reconnect Model version', version)
const currentVersionStr = versionToString(version as Version)
const reconnectVersionStr = versionToString(newVersion as Version)
if (currentVersionStr !== reconnectVersionStr) {
// It seems upgrade happened
location.reload()
}
})()
} catch (err) {
console.error(err)
}
@ -87,13 +102,13 @@ export async function connect (title: string): Promise<Client | undefined> {
}
try {
const version = await _client.findOne<Version>(core.class.Version, {})
version = await _client.findOne<Version>(core.class.Version, {})
console.log('Model version', version)
const requirdVersion = getMetadata(presentation.metadata.RequiredVersion)
if (requirdVersion !== undefined) {
if (requirdVersion !== undefined && version !== undefined) {
console.log('checking min model version', requirdVersion)
const versionStr = `${version?.major as number}.${version?.minor as number}.${version?.patch as number}`
const versionStr = versionToString(version)
if (version === undefined || requirdVersion !== versionStr) {
versionError = `${versionStr} => ${requirdVersion}`

View File

@ -175,7 +175,7 @@ class TServerStorage implements ServerStorage {
const txCUD = TxProcessor.extractTx(tx) as TxCUD<Doc>
if (!this.hierarchy.isDerived(txCUD._class, core.class.TxCUD)) {
// Skip unsupported tx
console.error('Unsupported transacton', tx)
console.error('Unsupported transaction', tx)
continue
}
const domain = this.hierarchy.getDomain(txCUD.objectClass)
@ -640,7 +640,7 @@ class TServerStorage implements ServerStorage {
}
if (tx.objectSpace === core.space.Model) {
// maintain hiearachy and triggers
// maintain hierarchy and triggers
this.hierarchy.tx(tx)
await this.triggers.tx(tx)
await this.modelDb.tx(tx)