11// import diff from 'hyperdiff'
2- import { P2PCommandResponse , TypesenseSearchResponse } from '../../@types/index'
2+ import { P2PCommandResponse } from '../../@types/index'
33import EventEmitter from 'node:events'
44import clone from 'lodash.clonedeep'
55
@@ -61,10 +61,6 @@ type DDOCache = {
6161 dht : Map < string , FindDDOResponse >
6262}
6363
64- // republish any ddos we are providing to the network every 4 hours
65- // (we can put smaller interval for testing purposes)
66- const REPUBLISH_INTERVAL_HOURS = 1000 * 60 * 60 * 4 // 4 hours
67-
6864let index = 0
6965
7066export class OceanP2P extends EventEmitter {
@@ -127,15 +123,13 @@ export class OceanP2P extends EventEmitter {
127123 this . _connections = { }
128124 this . _protocol = '/ocean/nodes/1.0.0'
129125
130- // this._interval = setInterval(this._pollPeers .bind(this), this._options.pollInterval)
126+ this . _interval = setInterval ( this . _flushAdvertiseQueue . bind ( this ) , 60 * 1000 ) // every 60 seconds
131127
132128 // only enable handling of commands if not bootstrap node
133129 if ( ! this . _config . isBootstrap ) {
134130 this . _libp2p . handle ( this . _protocol , handleProtocolCommands . bind ( this ) )
135131 }
136132
137- setInterval ( this . republishStoredDDOS . bind ( this ) , REPUBLISH_INTERVAL_HOURS )
138-
139133 this . _idx = index ++
140134
141135 this . _analyzeRemoteResponse = new Transform ( {
@@ -146,7 +140,7 @@ export class OceanP2P extends EventEmitter {
146140 // listen for indexer events and advertise did
147141 INDEXER_DDO_EVENT_EMITTER . addListener ( EVENTS . METADATA_CREATED , ( did ) => {
148142 P2P_LOGGER . info ( `Listened "${ EVENTS . METADATA_CREATED } "` )
149- this . advertiseDid ( did )
143+ this . advertiseString ( did )
150144 } )
151145 }
152146
@@ -755,17 +749,32 @@ export class OceanP2P extends EventEmitter {
755749 }
756750 }
757751
758- async advertiseDid ( did : string ) {
759- P2P_LOGGER . logMessage ( 'Advertising ' + did , true )
752+ async _flushAdvertiseQueue ( ) {
753+ if ( this . _pendingAdvertise . length > 0 ) {
754+ P2P_LOGGER . debug (
755+ `Flushing advertise queue with ${ this . _pendingAdvertise . length } items`
756+ )
757+ const list = JSON . parse ( JSON . stringify ( this . _pendingAdvertise ) )
758+ for ( const did of list ) {
759+ this . _pendingAdvertise = this . _pendingAdvertise . filter ( ( item ) => item !== did )
760+
761+ await this . advertiseString ( did )
762+ }
763+ // this._pendingAdvertise = []
764+ }
765+ }
766+
767+ async advertiseString ( did : string ) {
760768 try {
769+ const cid = await cidFromRawString ( did )
770+ P2P_LOGGER . debug ( 'Advertising "' + did + `" as CID:` + cid )
761771 const x = ( await this . getAllOceanPeers ( ) ) . length
762772 if ( x > 0 ) {
763- const cid = await cidFromRawString ( did )
764773 const multiAddrs = this . _libp2p . components . addressManager . getAddresses ( )
765774 // console.log('multiaddrs: ', multiAddrs)
766- await this . _libp2p . contentRouting . provide ( cid , multiAddrs )
775+ this . _libp2p . contentRouting . provide ( cid , multiAddrs )
767776 } else {
768- P2P_LOGGER . verbose (
777+ P2P_LOGGER . debug (
769778 'Could not find any Ocean peers. Nobody is listening at the moment, skipping...'
770779 )
771780 // save it for retry later
@@ -779,67 +788,50 @@ export class OceanP2P extends EventEmitter {
779788 }
780789 }
781790
782- async getProvidersForDid ( did : string ) {
783- P2P_LOGGER . logMessage ( 'Fetching providers for ' + did , true )
784- const cid = await cidFromRawString ( did )
791+ getCommonPeers (
792+ rets : Array < Array < { id : string ; multiaddrs : any [ ] } > >
793+ ) : Array < { id : string ; multiaddrs : any [ ] } > {
794+ return rets . reduce (
795+ ( acc , curr ) =>
796+ acc . filter ( ( item ) => curr . some ( ( el ) => el . id . toString ( ) === item . id . toString ( ) ) ) ,
797+ rets [ 0 ] // Initialize with first subarray
798+ )
799+ }
800+
801+ async getProvidersForStrings (
802+ input : string [ ] ,
803+ timeout ?: number
804+ ) : Promise < Array < { id : string ; multiaddrs : any [ ] } > > {
805+ const rets = await Promise . all (
806+ input . map ( async ( x ) => {
807+ const providers = await this . getProvidersForString ( x , timeout )
808+ return providers && providers . length > 0 ? providers : [ ] // Keep only valid results
809+ } )
810+ )
811+ return this . getCommonPeers ( rets )
812+ }
813+
814+ async getProvidersForString (
815+ input : string ,
816+ timeout ?: number
817+ ) : Promise < Array < { id : string ; multiaddrs : any [ ] } > > {
818+ P2P_LOGGER . logMessage ( 'Fetching providers for ' + input , true )
819+ const cid = await cidFromRawString ( input )
785820 const peersFound = [ ]
786821 try {
787822 const f = await this . _libp2p . contentRouting . findProviders ( cid , {
788- queryFuncTimeout : 20000 // 20 seconds
823+ queryFuncTimeout : timeout || 20000 // 20 seconds
789824 // on timeout the query ends with an abort signal => CodeError: Query aborted
790825 } )
791826 for await ( const value of f ) {
792827 peersFound . push ( value )
793828 }
794829 } catch ( e ) {
795- P2P_LOGGER . error ( 'getProvidersForDid ()' + e . message )
830+ P2P_LOGGER . error ( 'getProvidersForString ()' + e . message )
796831 }
797832 return peersFound
798833 }
799834
800- // republish the ddos we have
801- // related: https://github.com/libp2p/go-libp2p-kad-dht/issues/323
802- async republishStoredDDOS ( ) {
803- try {
804- if ( ! this . db || ! this . db . ddo ) {
805- P2P_LOGGER . logMessage (
806- `republishStoredDDOS() attempt aborted because there is no database!` ,
807- true
808- )
809- return
810- }
811- const db = this . db . ddo
812- const searchParameters = {
813- q : '*'
814- }
815-
816- const result : TypesenseSearchResponse [ ] = await db . search ( searchParameters )
817- if ( result && result . length > 0 && result [ 0 ] . found ) {
818- P2P_LOGGER . logMessage ( `Will republish cid for ${ result [ 0 ] . found } documents` , true )
819- result [ 0 ] . hits . forEach ( ( hit : any ) => {
820- const ddo = hit . document
821- this . advertiseDid ( ddo . id )
822- // populate hash table if not exists
823- // (even if no peers are listening, it still goes to the pending publish table)
824- if ( ! this . _ddoDHT . dht . has ( ddo . id ) ) {
825- this . cacheDDO ( ddo )
826- }
827- // todo check stuff like purgatory
828- } )
829- // update time
830- this . _ddoDHT . updated = new Date ( ) . getTime ( )
831- } else {
832- P2P_LOGGER . logMessage ( 'There is nothing to republish, skipping...' , true )
833- }
834- } catch ( err ) {
835- P2P_LOGGER . log (
836- LOG_LEVELS_STR . LEVEL_ERROR ,
837- `Caught "${ err . message } " on republishStoredDDOS()` ,
838- true
839- )
840- }
841- }
842-
843835 // cache a ddos object
844836 cacheDDO ( ddo : any ) {
845837 this . _ddoDHT . dht . set ( ddo . id , {
@@ -848,6 +840,7 @@ export class OceanP2P extends EventEmitter {
848840 lastUpdateTime : ddo . metadata . updated ,
849841 provider : this . getPeerId ( )
850842 } )
843+ this . _ddoDHT . updated = new Date ( ) . getTime ( )
851844 }
852845
853846 /**
@@ -893,7 +886,7 @@ export class OceanP2P extends EventEmitter {
893886 // if already added before, create() will return null, but still advertise it
894887 try {
895888 await db . create ( ddo )
896- await this . advertiseDid ( ddo . id )
889+ await this . advertiseString ( ddo . id )
897890 // populate hash table
898891 this . cacheDDO ( ddo )
899892 count ++
0 commit comments