File size: 2,240 Bytes
e92be04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { db } from '../config/gun.js';
import { gunSafe } from '../utils/gunUtils.js';
import axios from 'axios';

/**
 * SyncService — Phase 27: Cross-Hive Knowledge Transfer
 * 
 * Manages the synchronization of the Hive Knowledge Graph (HKG) 
 * across different relay nodes in the P2P mesh.
 */

class SyncService {
    /**
     * Returns a compact summary of all atomic facts in the local HKG.
     * Format: { factId: timestamp }
     */
    async getGraphSummary() {
        return new Promise((resolve) => {
            const summary = {};
            db.get('knowledge_graph').map().once((fact, id) => {
                if (fact && fact.timestamp) {
                    summary[id] = fact.timestamp;
                }
            });
            setTimeout(() => resolve(summary), 2000);
        });
    }

    /**
     * Fetches missing or outdated facts from a peer.
     * @param {string} peerUrl - The Gateway URL of the peer.
     * @param {object} remoteSummary - The summary from the peer.
     */
    async fetchMissingFacts(peerUrl, remoteSummary) {
        const localSummary = await this.getGraphSummary();
        const missingIds = Object.keys(remoteSummary).filter(id => {
            return !localSummary[id] || remoteSummary[id] > localSummary[id];
        });

        console.log(`[SYNC] Found ${missingIds.length} missing/outdated facts from ${peerUrl}`);
        
        const facts = [];
        for (const id of missingIds.slice(0, 50)) { // Limit per sync burst
            try {
                const res = await axios.get(`${peerUrl}/fact/${id}`, { timeout: 5000 });
                if (res.data) facts.push(res.data);
            } catch (e) {
                console.error(`[SYNC] Failed to fetch fact ${id} from ${peerUrl}: ${e.message}`);
            }
        }
        return facts;
    }

    /**
     * Ingests a list of atomic facts into the local HKG.
     */
    async mergeFacts(facts) {
        let count = 0;
        for (const fact of facts) {
            if (fact && fact.id) {
                db.get('knowledge_graph').get(fact.id).put(gunSafe(fact));
                count++;
            }
        }
        return count;
    }
}

export const syncService = new SyncService();