Fix swarm bootstrap for logo-less nodes
This commit is contained in:
@@ -13,11 +13,20 @@ import { buildAnnouncement } from '@/lib/swarm/discovery';
|
||||
import { verifySwarmRequest } from '@/lib/swarm/signature';
|
||||
import type { SwarmNodeInfo } from '@/lib/swarm/types';
|
||||
|
||||
const optionalUrlSchema = z.preprocess((value) => {
|
||||
if (typeof value !== 'string') {
|
||||
return value;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}, z.string().url().optional());
|
||||
|
||||
const announcementSchema = z.object({
|
||||
domain: z.string().min(1),
|
||||
name: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
logoUrl: z.string().url().optional(),
|
||||
logoUrl: optionalUrlSchema,
|
||||
publicKey: z.string().optional(),
|
||||
softwareVersion: z.string().optional(),
|
||||
userCount: z.number().optional(),
|
||||
|
||||
@@ -64,9 +64,21 @@ async function runBotTasks() {
|
||||
|
||||
async function runSwarmGossip() {
|
||||
try {
|
||||
const stats = await getSwarmStats();
|
||||
|
||||
// Recover from empty peer lists by periodically re-announcing to seeds.
|
||||
if (stats.activeNodes === 0) {
|
||||
const announceResult = await announceToSeeds();
|
||||
if (announceResult.successful.length > 0 || announceResult.failed.length > 0) {
|
||||
log('SWARM', `Re-announced to seeds: ${announceResult.successful.length} successful, ${announceResult.failed.length} failed`);
|
||||
}
|
||||
}
|
||||
|
||||
const result = await runGossipRound();
|
||||
if (result.contacted > 0) {
|
||||
log('SWARM', `Gossip: contacted ${result.contacted}, successful ${result.successful}, received ${result.totalNodesReceived} nodes`);
|
||||
} else if (stats.activeNodes === 0) {
|
||||
log('SWARM', 'No active swarm peers yet');
|
||||
}
|
||||
} catch (error) {
|
||||
log('SWARM', `Gossip error: ${error}`);
|
||||
|
||||
@@ -9,6 +9,15 @@ import { eq, sql } from 'drizzle-orm';
|
||||
import type { SwarmAnnouncement, SwarmNodeInfo, SwarmCapability } from './types';
|
||||
import { upsertSwarmNode, getSeedNodes, markNodeSuccess, markNodeFailure } from './registry';
|
||||
|
||||
function normalizeOptionalUrl(value: string | null | undefined): string | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build this node's announcement payload
|
||||
*/
|
||||
@@ -32,7 +41,7 @@ export async function buildAnnouncement(): Promise<SwarmAnnouncement> {
|
||||
if (node) {
|
||||
name = node.name;
|
||||
description = node.description ?? undefined;
|
||||
logoUrl = node.logoUrl ?? undefined;
|
||||
logoUrl = normalizeOptionalUrl(node.logoUrl);
|
||||
publicKey = node.publicKey ?? '';
|
||||
isNsfw = node.isNsfw;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user