Add api version check to client

This commit is contained in:
Andras Schmelczer 2025-11-23 22:12:49 +00:00
parent b1826907e7
commit 3ed2e4f666
10 changed files with 52 additions and 3 deletions

View file

@ -2,3 +2,4 @@ export const TIMEOUT_FOR_MERGING_HISTORY_ENTRIES_IN_SECONDS = 60;
export const DIFF_CACHE_SIZE_MB = 2;
export const MAX_LOG_MESSAGE_COUNT = 100000;
export const MAX_HISTORY_ENTRY_COUNT = 5000;
export const SUPPORTED_API_VERSION = 1;

View file

@ -25,6 +25,8 @@ export type { PersistenceProvider } from "./persistence/persistence";
export type { CursorSpan } from "./services/types/CursorSpan";
export type { ClientCursors } from "./services/types/ClientCursors";
export type { NetworkConnectionStatus } from "./types/network-connection-status";
export type { ServerVersionMismatchError } from "./services/server-version-mismatch-error";
export type { AuthenticationError } from "./services/authentication-error";
export type { MaybeOutdatedClientCursors } from "./types/maybe-outdated-client-cursors";
export { DocumentSyncStatus } from "./types/document-sync-status";
export { SyncClient } from "./sync-client";

View file

@ -0,0 +1,6 @@
export class AuthenticationError extends Error {
public constructor(message: string) {
super(message);
this.name = "AuthenticationError";
}
}

View file

@ -1,9 +1,13 @@
import { createPromise } from "../utils/create-promise";
import { SUPPORTED_API_VERSION } from "../consts";
import { AuthenticationError } from "./authentication-error";
import { ServerVersionMismatchError } from "./server-version-mismatch-error";
import type { SyncService } from "./sync-service";
import type { PingResponse } from "./types/PingResponse";
export interface ServerConfigData {
mergeableFileExtensions: string[];
supportedApiVersion: number;
isAuthenticated: boolean;
}
export class ServerConfig {
@ -15,6 +19,22 @@ export class ServerConfig {
public async initialize(): Promise<void> {
this.response = this.syncService.ping();
this.config = await this.response;
if (this.config.supportedApiVersion !== SUPPORTED_API_VERSION) {
const shouldUpgradeClient =
this.config.supportedApiVersion > SUPPORTED_API_VERSION;
throw new ServerVersionMismatchError(
`Unsupported API version: ${this.config.supportedApiVersion}. Consider upgrading the ${
shouldUpgradeClient ? "client" : "sync-server"
} to ensure compatibility.`
);
}
if (!this.config.isAuthenticated) {
throw new AuthenticationError(
"Failed to authenticate with the sync-server."
);
}
}
public async checkConnection(forceUpdate = false): Promise<{

View file

@ -0,0 +1,6 @@
export class ServerVersionMismatchError extends Error {
public constructor(message: string) {
super(message);
this.name = "ServerVersionMismatchError";
}
}

View file

@ -17,4 +17,9 @@ export interface PingResponse {
* List of file extensions that are allowed to be merged.
*/
mergeableFileExtensions: string[];
/**
* API version ensuring backwards & forwards compatibility between the client
* and server.
*/
supportedApiVersion: number;
}

View file

@ -220,8 +220,6 @@ export class SyncClient {
}
this.hasStarted = true;
await this.serverConfig.initialize();
if (
!this.unloadTelemetry &&
this.settings.getSettings().enableTelemetry
@ -311,6 +309,7 @@ export class SyncClient {
this.resetInMemoryState();
this.hasStartedOfflineSync = false;
this.hasFinishedOfflineSync = false;
this.serverConfig.reset();
// restart syncing
this.fetchController.finishReset();
@ -457,6 +456,8 @@ export class SyncClient {
private async startSyncing(): Promise<void> {
this.checkIfDestroyed();
await this.serverConfig.initialize();
if (!this.hasStartedOfflineSync) {
this.hasStartedOfflineSync = true;
await this.syncer.scheduleSyncForOfflineChanges();

View file

@ -16,3 +16,5 @@ pub const DEFAULT_LOG_DIRECTORY: &str = "logs";
pub const DEFAULT_LOG_ROTATION_INTERVAL: Duration = Duration::from_secs(60 * 60 * 24); // 1 day
pub const DEFAULT_MERGEABLE_FILE_EXTENSIONS: &[&str] = &["md", "txt"];
pub const SUPPORTED_API_VERSION: u32 = 1;

View file

@ -11,6 +11,7 @@ use serde::Deserialize;
use super::{auth::auth, responses::PingResponse};
use crate::{
app_state::{AppState, database::models::VaultId},
consts::SUPPORTED_API_VERSION,
errors::SyncServerError,
utils::normalize::normalize,
};
@ -34,5 +35,6 @@ pub async fn ping(
server_version: env!("CARGO_PKG_VERSION").to_owned(),
is_authenticated,
mergeable_file_extensions: state.config.server.mergeable_file_extensions.clone(),
supported_api_version: SUPPORTED_API_VERSION,
}))
}

View file

@ -19,6 +19,10 @@ pub struct PingResponse {
/// List of file extensions that are allowed to be merged.
pub mergeable_file_extensions: Vec<String>,
/// API version ensuring backwards & forwards compatibility between the client
/// and server.
pub supported_api_version: u32,
}
/// Response to a fetch latest documents request.