feat: enhance storage stats and cluster health reporting
- Introduced new data structures for bucket and storage statistics, including BucketSummary, StorageStats, and ClusterHealth. - Implemented runtime statistics tracking for buckets, including object count and total size. - Added methods to retrieve storage stats and bucket summaries in the FileStore. - Enhanced the SmartStorage interface to expose storage stats and cluster health. - Implemented tests for runtime stats, cluster health, and credential management. - Added support for runtime-managed credentials with atomic replacement. - Improved filesystem usage reporting for storage locations.
This commit is contained in:
+134
-4
@@ -1,15 +1,20 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import * as paths from './paths.js';
|
||||
|
||||
/**
|
||||
* Authentication configuration
|
||||
*/
|
||||
export interface IStorageCredential {
|
||||
accessKeyId: string;
|
||||
secretAccessKey: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication configuration
|
||||
*/
|
||||
export interface IAuthConfig {
|
||||
enabled: boolean;
|
||||
credentials: Array<{
|
||||
accessKeyId: string;
|
||||
secretAccessKey: string;
|
||||
}>;
|
||||
credentials: IStorageCredential[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,6 +118,105 @@ export interface ISmartStorageConfig {
|
||||
cluster?: IClusterConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logical bucket stats maintained by the Rust runtime.
|
||||
* Values are initialized from native storage on startup and updated on smartstorage mutations.
|
||||
*/
|
||||
export interface IBucketSummary {
|
||||
name: string;
|
||||
objectCount: number;
|
||||
totalSizeBytes: number;
|
||||
creationDate?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filesystem-level capacity snapshot for the storage directory or configured drive path.
|
||||
*/
|
||||
export interface IStorageLocationSummary {
|
||||
path: string;
|
||||
totalBytes?: number;
|
||||
availableBytes?: number;
|
||||
usedBytes?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime storage stats served by the Rust core without issuing S3 list calls.
|
||||
*/
|
||||
export interface IStorageStats {
|
||||
bucketCount: number;
|
||||
totalObjectCount: number;
|
||||
totalStorageBytes: number;
|
||||
buckets: IBucketSummary[];
|
||||
storageDirectory: string;
|
||||
storageLocations?: IStorageLocationSummary[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Known peer status from the local node's current cluster view.
|
||||
*/
|
||||
export interface IClusterPeerHealth {
|
||||
nodeId: string;
|
||||
status: 'online' | 'suspect' | 'offline';
|
||||
quicAddress?: string;
|
||||
s3Address?: string;
|
||||
driveCount?: number;
|
||||
lastHeartbeat?: number;
|
||||
missedHeartbeats?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local drive health as measured by smartstorage's runtime probes.
|
||||
*/
|
||||
export interface IClusterDriveHealth {
|
||||
index: number;
|
||||
path: string;
|
||||
status: 'online' | 'degraded' | 'offline' | 'healing';
|
||||
totalBytes?: number;
|
||||
usedBytes?: number;
|
||||
availableBytes?: number;
|
||||
errorCount?: number;
|
||||
lastError?: string;
|
||||
lastCheck?: number;
|
||||
erasureSetId?: number;
|
||||
}
|
||||
|
||||
export interface IClusterErasureHealth {
|
||||
dataShards: number;
|
||||
parityShards: number;
|
||||
chunkSizeBytes: number;
|
||||
totalShards: number;
|
||||
readQuorum: number;
|
||||
writeQuorum: number;
|
||||
erasureSetCount: number;
|
||||
}
|
||||
|
||||
export interface IClusterRepairHealth {
|
||||
active: boolean;
|
||||
scanIntervalMs?: number;
|
||||
lastRunStartedAt?: number;
|
||||
lastRunCompletedAt?: number;
|
||||
lastDurationMs?: number;
|
||||
shardsChecked?: number;
|
||||
shardsHealed?: number;
|
||||
failed?: number;
|
||||
lastError?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cluster runtime health from the Rust core.
|
||||
* When clustering is disabled, the response is `{ enabled: false }`.
|
||||
*/
|
||||
export interface IClusterHealth {
|
||||
enabled: boolean;
|
||||
nodeId?: string;
|
||||
quorumHealthy?: boolean;
|
||||
majorityHealthy?: boolean;
|
||||
peers?: IClusterPeerHealth[];
|
||||
drives?: IClusterDriveHealth[];
|
||||
erasure?: IClusterErasureHealth;
|
||||
repairs?: IClusterRepairHealth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default configuration values
|
||||
*/
|
||||
@@ -205,6 +309,11 @@ type TRustStorageCommands = {
|
||||
start: { params: { config: Required<ISmartStorageConfig> }; result: {} };
|
||||
stop: { params: {}; result: {} };
|
||||
createBucket: { params: { name: string }; result: {} };
|
||||
getStorageStats: { params: {}; result: IStorageStats };
|
||||
listBucketSummaries: { params: {}; result: IBucketSummary[] };
|
||||
listCredentials: { params: {}; result: IStorageCredential[] };
|
||||
replaceCredentials: { params: { credentials: IStorageCredential[] }; result: {} };
|
||||
getClusterHealth: { params: {}; result: IClusterHealth };
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -274,6 +383,27 @@ export class SmartStorage {
|
||||
return { name: bucketNameArg };
|
||||
}
|
||||
|
||||
public async getStorageStats(): Promise<IStorageStats> {
|
||||
return this.bridge.sendCommand('getStorageStats', {});
|
||||
}
|
||||
|
||||
public async listBucketSummaries(): Promise<IBucketSummary[]> {
|
||||
return this.bridge.sendCommand('listBucketSummaries', {});
|
||||
}
|
||||
|
||||
public async listCredentials(): Promise<IStorageCredential[]> {
|
||||
return this.bridge.sendCommand('listCredentials', {});
|
||||
}
|
||||
|
||||
public async replaceCredentials(credentials: IStorageCredential[]): Promise<void> {
|
||||
await this.bridge.sendCommand('replaceCredentials', { credentials });
|
||||
this.config.auth.credentials = credentials.map((credential) => ({ ...credential }));
|
||||
}
|
||||
|
||||
public async getClusterHealth(): Promise<IClusterHealth> {
|
||||
return this.bridge.sendCommand('getClusterHealth', {});
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
await this.bridge.sendCommand('stop', {});
|
||||
this.bridge.kill();
|
||||
|
||||
Reference in New Issue
Block a user