Skip to content

ServerTransferQueue

The ServerTransferQueue table manages the pipeline for transferring player characters between servers in a QS-Bridge cluster. Each row represents a transfer request and tracks its progress through a multi-step state machine — from initial request through character snapshot, transit, and completion on the destination server.


Scope

🌍 Global — Transfer records are visible to all servers and the admin panel. Both the source and destination servers must be able to read the transfer record to coordinate the handoff.


Schema

Column Type Constraints Description
transfer_id u64 Primary Key, auto-increment Unique identifier for this transfer request
player_id String Indexed Platform-wide player identifier of the transferring player
from_server_id String The server_id of the origin server
to_server_id String The server_id of the destination server
status String Current transfer state (see state machine below)
character_snapshot String Serialized character data (JSON format)
requested_at Timestamp When the transfer was initiated
completed_at Option<Timestamp> When the transfer reached a terminal state (None if in progress)

Rust Definition

#[spacetimedb::table(public, name = server_transfer_queue)]
pub struct ServerTransferQueue {
    #[primary_key]
    #[auto_inc]
    pub transfer_id: u64,
    #[index(btree)]
    pub player_id: String,
    pub from_server_id: String,
    pub to_server_id: String,
    pub status: String,
    pub character_snapshot: String,
    pub requested_at: Timestamp,
    pub completed_at: Option<Timestamp>,
}

Transfer State Machine

Each transfer progresses through a defined set of states:

graph LR
    Pending["pending"] --> InTransit["in_transit"]
    InTransit --> Completed["completed"]
    Pending --> Failed1["failed"]
    InTransit --> Failed2["failed"]
Status Description
pending Transfer requested; character snapshot is being captured on the source server
in_transit Snapshot captured; waiting for the destination server to accept and restore
completed Character successfully restored on the destination server
failed Transfer failed at any stage — character data remains on the source server

State Transitions

  1. pending — The source server receives the transfer request and begins serializing the player's character data (inventory, stats, position, etc.) into the character_snapshot field.

  2. in_transit — The source server has captured the snapshot and disconnected the player. The destination server detects the in_transit record (via subscription) and begins restoring the character.

  3. completed — The destination server has successfully deserialized and applied the character snapshot. The player can now connect to the destination server.

  4. failed — An error occurred during snapshot capture, transit, or restoration. The player's original data on the source server is preserved.


Usage Patterns

Transfer Initiation

A transfer is initiated when a player requests to move to another server (or an admin forces a transfer):

// Pseudocode — initiate transfer
fn request_transfer(player_id: &str, from: &str, to: &str) {
    ServerTransferQueue::insert(ServerTransferQueue {
        transfer_id: 0, // auto-incremented
        player_id: player_id.to_string(),
        from_server_id: from.to_string(),
        to_server_id: to.to_string(),
        status: "pending".to_string(),
        character_snapshot: String::new(), // Populated during snapshot
        requested_at: Timestamp::now(),
        completed_at: None,
    });
}

Character Snapshot

The character_snapshot field stores a JSON-serialized representation of the player's full character state. Like GlobalVault's item_data, this is an opaque payload — the platform does not interpret its contents. The game-specific sub-database defines the snapshot schema.

Example snapshot structure (game-specific):

{
  "character_name": "PlayerOne",
  "level": 42,
  "position": { "x": 100.5, "y": 200.3, "z": 50.0 },
  "inventory": [ /* serialized items */ ],
  "stats": { "health": 100, "stamina": 80 },
  "skills": { /* skill tree data */ },
  "equipment": { /* equipped items */ }
}

Coordination with Player Presence

During a transfer, the player's PlayerServerPresence row ensures they cannot connect to any server while the transfer is in flight:

  1. Player is disconnected from the source server → presence row remains (preventing reconnection).
  2. Transfer reaches completed state.
  3. Presence row is updated to reflect the destination server_id.
  4. Player connects to the destination server.

Failure Recovery

If a transfer fails (status = "failed"), the character data remains on the source server. The character_snapshot may still contain the captured data for diagnostic purposes. An administrator can review the failed transfer in the panel and decide whether to retry or cancel.


Transfer operations are primarily managed by game-specific reducers in the sub-database layer, as the snapshot format is game-dependent. Platform-level coordination happens through table subscriptions rather than dedicated platform reducers.


Subscriber Query Purpose
Source Server SELECT * FROM server_transfer_queue WHERE from_server_id = '{self}' Monitor outbound transfers
Destination Server SELECT * FROM server_transfer_queue WHERE to_server_id = '{self}' Detect incoming transfers to process
Admin Panel SELECT * FROM server_transfer_queue Transfer monitoring, failure review

For full subscription architecture, see Subscriptions.