Skip to content

System Overview

Architecture Diagram

Module Responsibilities

platform-api

Shared Dubbo interface definitions that all modules depend on:

  • BlockChainService - Blockchain operations
  • DistributedStorageService - Storage operations
  • Common DTOs and response types

platform-backend

Multi-module backend service (Dubbo Consumer):

SubmoduleResponsibility
backend-webREST controllers, JWT filters, rate limiting, CORS
backend-serviceBusiness logic, Saga orchestration, Outbox publishing
backend-daoMyBatis Plus mappers, entities, VOs
backend-apiInternal API interfaces
backend-commonUtilities, constants, annotations

platform-fisco

Blockchain integration service (Dubbo Provider):

  • Smart contract interaction (Storage.sol, Sharing.sol)
  • Multi-chain adapters (Local FISCO, BSN FISCO, Besu)
  • Certificate management

platform-storage

Distributed storage service (Dubbo Provider):

  • Multi-node S3 client management
  • Fault domain management
  • Consistent hashing and rebalancing
  • File encryption/decryption

Core Business Flow

File Upload & Attestation

File Download Flow

Download Strategy Comparison:

StrategyUse CaseCharacteristics
Memory ModeSmall files (< 50MB)Load all chunks into memory then decrypt, fast
Streaming ModeLarge files (≥ 50MB)Uses StreamSaver.js, download while writing, low memory
Backend ProxySpecial scenariosBackend proxies download, for environments without direct S3 access

Key Chain Decryption: Each chunk is encrypted with an independent key. During download, keys are matched by chunkIndex order for decryption.

File Sharing Flow

Friend Sharing

Share Type Comparison:

TypeAccess ControlExpiryCharacteristics
Public ShareNoneConfigurableAnyone can access via link
Private SharePasswordConfigurablePassword required for access
Friend ShareFriendshipPermanentOnly specified friend can view, supports read status

Saga Compensation Flow

StepForward ActionCompensation
PENDINGInitialize-
S3_UPLOADINGStore chunksClean stored chunks
S3_UPLOADEDChunks storedDelete S3 files
CHAIN_STORINGBlockchain attestationMark chain record deleted
COMPLETEDCommit-

Compensation Strategy: Exponential backoff (initial 1s, max 5 retries), then manual queue.

Saga State Machine

The FileSagaOrchestrator manages the complete state machine:

Transactional Outbox Pattern

RecordPlatform uses the Outbox pattern for reliable event publishing to RabbitMQ.

How It Works

Components

ComponentResponsibility
OutboxServiceAppends events within business transaction
OutboxPublisherBackground polling and publishing (2s interval)
outbox_event tablePersistent event store with tenant isolation

Guarantees

  • At-least-once delivery: Events survive broker unavailability
  • Transactional consistency: Event created in same DB transaction as business data
  • Tenant-aware polling: Each tenant's events processed independently

Configuration

yaml
outbox:
  publisher:
    batch-size: 100
    poll-interval-ms: 2000
    max-retries: 5
  cleanup:
    sent-retention-days: 7
    failed-retention-days: 30
    cron: 0 0 3 * * ?

CQRS Architecture

File module uses Command Query Responsibility Segregation:

Virtual Thread Async Methods

Query service provides async methods using Java 21 Virtual Threads:

  • getUserFilesListAsync()
  • getFileAddressAsync()
  • getFileDecryptInfoAsync()

File Version Chain

The file version chain allows a single logical file to have multiple historical versions, linked together in a chain structure. See the dedicated File Version Chain page for detailed design.

Core Fields

FieldDescription
version_group_idShared group ID across all versions of the same logical file
parent_version_idParent version ID (null for first version)
is_latestMarks the latest version in the chain (only one true per group)

Version API

  • GET /api/v1/files/{id}/versions — List the version chain for a file
  • POST /api/v1/files/{id}/versions — Mark an existing file as parent for a new upload (via targetFileId)

Multi-tenancy

Isolation Strategy

LayerIsolation Method
Databasetenant_id field, MyBatis auto-inject
RedisKey prefix tenant:{tenantId}:
S3 StoragePath /{tenantId}/{userId}/
DubboContext propagation TenantContext

Tenant Context Control

@TenantScope annotation for declarative tenant isolation:

java
// Cross-tenant query (scheduled tasks)
@TenantScope(ignoreIsolation = true)
@Scheduled(cron = "0 0 3 * * ?")
public void cleanupDeletedFiles() { ... }

// Switch to specific tenant
@TenantScope(tenantId = 1)
public void migrateDataForTenant() { ... }

Real-time Notifications (SSE)

Server-Sent Events provide real-time updates to connected clients.

Multi-Connection Architecture

The system supports multiple simultaneous connections per user:

Connection Configuration

ParameterDefaultDescription
Max connections per user5Oldest connection closed when exceeded
Heartbeat interval30sKeep-alive signal
Connection timeout30mAuto-close after inactivity
Reconnect delay (base)2sBase delay for exponential client reconnect
Reconnect delay (max)30sUpper bound for reconnect backoff
Max reconnect attempts5Falls back to manual reconnect after limit

Event Types

EventPayloadDescription
connected{ connectionId }Initial connection confirmation
notification{ title, content }General notification
message-received{ conversationId, preview }New message in conversation
file-record-success{ fileName, fileHash, status }File attestation success notification
file-record-failed{ fileName, status, reason }File attestation failure notification
announcement-published{ id, title }System announcement
ticket-updated{ ticketId, status }Ticket status change
badge-update{ unreadMessages, tickets }UI badge count update
friend-request{ requesterName, ... }New friend request
friend-accepted{ friendName, ... }Friend request accepted
friend-share{ sharerName, fileCount, ... }Friend file sharing
audit-alert{ type, message, details, severity }Audit anomaly alert (admin/monitor)
integrity-alert{ alertType, fileHash, details }Storage integrity anomaly alert (admin)

SSE Authentication Handshake

SSE connections use a short-lived one-time token:

  1. Call POST /api/v1/auth/tokens/sse with regular JWT auth
  2. Connect via GET /api/v1/sse/connect?token={sseToken}&connectionId={optional}

GET /api/v1/sse/connect is publicly exposed in Spring Security but still requires valid short-lived token authentication.

Monitoring Capacity Semantics

System monitoring now includes:

  • GET /api/v1/system/storage-capacity

Response shape includes:

  • Cluster totals: totalCapacityBytes, usedCapacityBytes, availableCapacityBytes
  • Data quality flags: degraded, source
  • Detailed aggregates: nodes[], domains[]

GET /api/v1/system/stats now uses this capacity result for totalStorage. Only when Dubbo capacity RPC fails does it fall back to totalFiles * 1MB, logging marker MONITOR_STORAGE_CAPACITY_FALLBACK.

Download Strategy (Frontend)

Frontend selects download strategy by file size and browser capability:

  • Small files: in-memory download
  • Large files: prefer streaming download
  • Very large files or unsupported browsers: backend proxy / guarded fallback

Default thresholds (platform-frontend/src/lib/utils/fileSize.ts):

Threshold ConstantDefault
LARGE_FILE_WARNING_THRESHOLD500MB
STREAMING_RECOMMENDED_THRESHOLD1GB
MAX_SAFE_INMEMORY_SIZE2GB
MAX_DOWNLOADABLE_SIZE100GB

Quota Governance

The platform enforces per-user and per-tenant storage quotas with two enforcement modes:

  • SHADOW (default): Quota violations are logged and alerted but uploads are not blocked. Use during rollout to observe impact.
  • ENFORCE: Uploads exceeding quota are rejected with 50013 QUOTA_EXCEEDED.

Rollout Strategy:

PropertyDescription
quota.enforcement-modeGlobal mode: SHADOW or ENFORCE
quota.rollout.strategyTENANT_WHITELIST — only whitelisted tenants use ENFORCE
quota.rollout.enforce-tenant-whitelistComma-separated tenant IDs for ENFORCE mode
quota.rollout.force-shadowOverride to force SHADOW for all tenants

Reconciliation: A scheduled job (quota.reconcile.cron, default every 30 minutes) recalculates usage snapshots to correct any drift between cached and actual usage.

API Endpoints:

  • GET /api/v1/files/quota — Current user quota status
  • POST /api/v1/admin/quota/rollout/audits — Write rollout audit record (admin)
  • GET /api/v1/admin/quota/rollout/audits — Query rollout audit record (admin)

Batch Download

The frontend supports selecting multiple files for batch download:

  1. Select: User selects files from the file list
  2. Parallel Download: Files are downloaded concurrently (up to configurable concurrency limit)
  3. Auto-Retry: Failed downloads are automatically retried
  4. Metrics Report: After completion, the frontend reports batch quality metrics via POST /api/v1/files/download-batches/report

The report payload includes total files, successful/failed counts, retry count, total duration, and error type breakdown — used for backend quality observability.

Keyword Search Modes

File queries (GET /api/v1/files) support a keywordMode parameter that controls how the keyword is matched:

ModeFile Name MatchingFile Hash MatchingUse Case
FUZZY (default)LIKE %keyword%LIKE %keyword%General search
PREFIXLIKE keyword%Exact matchFaster indexed lookup
EXACT_HASHNot searchedExact match onlyDirect hash lookup
AUTODepends on keywordDepends on keywordSmart detection

AUTO mode inspects the keyword: if it matches the hex hash pattern (/^[0-9a-fA-F]{32,128}$/), it resolves to EXACT_HASH; otherwise it resolves to PREFIX.

Frontend Leader Election

For multi-tab scenarios, frontend uses BroadcastChannel for leader election:

  • Leader tab: Maintains single SSE connection
  • Follower tabs: Receive events via BroadcastChannel
  • Failover: Auto-elect new leader when leader tab closes

This prevents multiple SSE connections from same browser, reducing server load.

Released under the Apache 2.0 License.