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 { verifySwarmRequest } from '@/lib/swarm/signature';
|
||||||
import type { SwarmNodeInfo } from '@/lib/swarm/types';
|
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({
|
const announcementSchema = z.object({
|
||||||
domain: z.string().min(1),
|
domain: z.string().min(1),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
logoUrl: z.string().url().optional(),
|
logoUrl: optionalUrlSchema,
|
||||||
publicKey: z.string().optional(),
|
publicKey: z.string().optional(),
|
||||||
softwareVersion: z.string().optional(),
|
softwareVersion: z.string().optional(),
|
||||||
userCount: z.number().optional(),
|
userCount: z.number().optional(),
|
||||||
|
|||||||
@@ -64,9 +64,21 @@ async function runBotTasks() {
|
|||||||
|
|
||||||
async function runSwarmGossip() {
|
async function runSwarmGossip() {
|
||||||
try {
|
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();
|
const result = await runGossipRound();
|
||||||
if (result.contacted > 0) {
|
if (result.contacted > 0) {
|
||||||
log('SWARM', `Gossip: contacted ${result.contacted}, successful ${result.successful}, received ${result.totalNodesReceived} nodes`);
|
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) {
|
} catch (error) {
|
||||||
log('SWARM', `Gossip error: ${error}`);
|
log('SWARM', `Gossip error: ${error}`);
|
||||||
|
|||||||
@@ -9,6 +9,15 @@ import { eq, sql } from 'drizzle-orm';
|
|||||||
import type { SwarmAnnouncement, SwarmNodeInfo, SwarmCapability } from './types';
|
import type { SwarmAnnouncement, SwarmNodeInfo, SwarmCapability } from './types';
|
||||||
import { upsertSwarmNode, getSeedNodes, markNodeSuccess, markNodeFailure } from './registry';
|
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
|
* Build this node's announcement payload
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +41,7 @@ export async function buildAnnouncement(): Promise<SwarmAnnouncement> {
|
|||||||
if (node) {
|
if (node) {
|
||||||
name = node.name;
|
name = node.name;
|
||||||
description = node.description ?? undefined;
|
description = node.description ?? undefined;
|
||||||
logoUrl = node.logoUrl ?? undefined;
|
logoUrl = normalizeOptionalUrl(node.logoUrl);
|
||||||
publicKey = node.publicKey ?? '';
|
publicKey = node.publicKey ?? '';
|
||||||
isNsfw = node.isNsfw;
|
isNsfw = node.isNsfw;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user