149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
// SCI Replication Service
|
|
// Global Replication Grid (GRG) with 30s metadata hashing
|
|
|
|
import prisma from '@/shared/database/prisma';
|
|
import { createHash } from 'crypto';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import { logger } from '@/infrastructure/monitoring/logger';
|
|
|
|
|
|
const METADATA_HASH_INTERVAL = 30000; // 30 seconds
|
|
|
|
export interface ReplicationRequest {
|
|
zoneId: string;
|
|
targetZoneId: string;
|
|
replicationType: 'metadata' | 'full' | 'incremental';
|
|
}
|
|
|
|
export class SciReplicationService {
|
|
private hashIntervals: Map<string, NodeJS.Timeout> = new Map();
|
|
|
|
/**
|
|
* Start replication between zones
|
|
*/
|
|
async startReplication(request: ReplicationRequest): Promise<{ replicationId: string }> {
|
|
const replicationId = `REP-${uuidv4()}`;
|
|
|
|
// Create replication record
|
|
await prisma.sovereignReplication.create({
|
|
data: {
|
|
replicationId,
|
|
zoneId: request.zoneId,
|
|
targetZoneId: request.targetZoneId,
|
|
replicationType: request.replicationType,
|
|
metadataHash: '',
|
|
lastHashTime: new Date(),
|
|
status: 'active',
|
|
},
|
|
});
|
|
|
|
// Start metadata hashing interval
|
|
this.startMetadataHashing(replicationId, request.zoneId);
|
|
|
|
logger.info('SCI: Started replication', {
|
|
replicationId,
|
|
zoneId: request.zoneId,
|
|
targetZoneId: request.targetZoneId,
|
|
replicationType: request.replicationType,
|
|
});
|
|
|
|
return { replicationId };
|
|
}
|
|
|
|
/**
|
|
* Start metadata hashing every 30 seconds
|
|
*/
|
|
private startMetadataHashing(replicationId: string, zoneId: string): void {
|
|
const interval = setInterval(async () => {
|
|
try {
|
|
await this.updateMetadataHash(replicationId, zoneId);
|
|
} catch (error) {
|
|
logger.error('SCI: Metadata hashing failed', { error, replicationId, zoneId });
|
|
}
|
|
}, METADATA_HASH_INTERVAL);
|
|
|
|
this.hashIntervals.set(replicationId, interval);
|
|
}
|
|
|
|
/**
|
|
* Update metadata hash
|
|
*/
|
|
private async updateMetadataHash(replicationId: string, zoneId: string): Promise<void> {
|
|
// Get zone metadata
|
|
const zone = await prisma.sovereignComputeZone.findUnique({
|
|
where: { zoneId },
|
|
include: {
|
|
contracts: true,
|
|
attestations: {
|
|
where: { status: 'verified' },
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!zone) {
|
|
throw new Error('Zone not found');
|
|
}
|
|
|
|
// Create metadata object
|
|
const metadata = {
|
|
zoneId: zone.zoneId,
|
|
status: zone.status,
|
|
contractCount: zone.contracts.length,
|
|
verifiedAttestationCount: zone.attestations.length,
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
|
|
// Calculate hash
|
|
const metadataString = JSON.stringify(metadata);
|
|
const metadataHash = createHash('sha256').update(metadataString).digest('hex');
|
|
|
|
// Update replication record
|
|
await prisma.sovereignReplication.update({
|
|
where: { replicationId },
|
|
data: {
|
|
metadataHash,
|
|
lastHashTime: new Date(),
|
|
},
|
|
});
|
|
|
|
logger.debug('SCI: Updated metadata hash', { replicationId, metadataHash });
|
|
}
|
|
|
|
/**
|
|
* Stop replication
|
|
*/
|
|
async stopReplication(replicationId: string): Promise<void> {
|
|
// Stop hashing interval
|
|
const interval = this.hashIntervals.get(replicationId);
|
|
if (interval) {
|
|
clearInterval(interval);
|
|
this.hashIntervals.delete(replicationId);
|
|
}
|
|
|
|
// Update replication status
|
|
await prisma.sovereignReplication.update({
|
|
where: { replicationId },
|
|
data: { status: 'paused' },
|
|
});
|
|
|
|
logger.info('SCI: Stopped replication', { replicationId });
|
|
}
|
|
|
|
/**
|
|
* Get replication status
|
|
*/
|
|
async getReplicationStatus(replicationId: string) {
|
|
const replication = await prisma.sovereignReplication.findUnique({
|
|
where: { replicationId },
|
|
include: {
|
|
zone: true,
|
|
},
|
|
});
|
|
|
|
return replication;
|
|
}
|
|
}
|
|
|
|
export const sciReplicationService = new SciReplicationService();
|
|
|