search
This commit is contained in:
@@ -27,12 +27,6 @@ import (
|
||||
"github.com/libp2p/go-libp2p/p2p/security/noise"
|
||||
)
|
||||
|
||||
// activeSearch tracks an in-flight distributed peer search for one user.
|
||||
type activeSearch struct {
|
||||
queryID string
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
*common.LongLivedStreamRecordedService[interface{}] // change type of stream
|
||||
PS *pubsubs.PubSub
|
||||
@@ -43,9 +37,8 @@ type Node struct {
|
||||
isIndexer bool
|
||||
peerRecord *indexer.PeerRecord
|
||||
|
||||
// activeSearches: one streaming search per user; new search cancels previous.
|
||||
activeSearchesMu sync.Mutex
|
||||
activeSearches map[string]*activeSearch
|
||||
// peerSearches: one active peer search per user; new search cancels previous.
|
||||
peerSearches *common.SearchTracker
|
||||
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
@@ -85,7 +78,7 @@ func InitNode(isNode bool, isIndexer bool) (*Node, error) {
|
||||
PeerID: h.ID(),
|
||||
isIndexer: isIndexer,
|
||||
LongLivedStreamRecordedService: common.NewStreamRecordedService[interface{}](h, 1000),
|
||||
activeSearches: map[string]*activeSearch{},
|
||||
peerSearches: common.NewSearchTracker(),
|
||||
}
|
||||
// Register the bandwidth probe handler so any peer measuring this node's
|
||||
// throughput can open a dedicated probe stream and read the echo.
|
||||
@@ -204,32 +197,21 @@ func (d *Node) publishPeerRecord(
|
||||
}
|
||||
|
||||
// SearchPeerRecord starts a distributed peer search via ProtocolSearchPeer.
|
||||
// userKey identifies the requesting user — a new call cancels any previous
|
||||
// search for the same user. Results are pushed to onResult as they arrive.
|
||||
// The function returns when the search stream closes (idle timeout or indexer unreachable).
|
||||
// A new call for the same userKey cancels any previous search.
|
||||
// Results are pushed to onResult as they arrive; the function returns when
|
||||
// the stream closes (idle timeout, explicit cancel, or indexer unreachable).
|
||||
func (d *Node) SearchPeerRecord(userKey, needle string, onResult func(common.SearchHit)) {
|
||||
fmt.Println("SearchPeerRecord", needle)
|
||||
logger := oclib.GetLogger()
|
||||
|
||||
idleTimeout := common.SearchIdleTimeout()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
// Register cancels any previous search for userKey and starts the idle timer.
|
||||
// The composite key doubles as QueryID so the indexer echoes it back.
|
||||
searchKey := d.peerSearches.Register(userKey, cancel, idleTimeout)
|
||||
defer d.peerSearches.Cancel(searchKey)
|
||||
|
||||
d.activeSearchesMu.Lock()
|
||||
if prev, ok := d.activeSearches[userKey]; ok {
|
||||
prev.cancel()
|
||||
}
|
||||
queryID := uuid.New().String()
|
||||
d.activeSearches[userKey] = &activeSearch{queryID: queryID, cancel: cancel}
|
||||
d.activeSearchesMu.Unlock()
|
||||
|
||||
defer func() {
|
||||
cancel()
|
||||
d.activeSearchesMu.Lock()
|
||||
if cur, ok := d.activeSearches[userKey]; ok && cur.queryID == queryID {
|
||||
delete(d.activeSearches, userKey)
|
||||
}
|
||||
d.activeSearchesMu.Unlock()
|
||||
}()
|
||||
|
||||
req := common.SearchPeerRequest{QueryID: queryID}
|
||||
req := common.SearchPeerRequest{QueryID: searchKey}
|
||||
if pid, err := pp.Decode(needle); err == nil {
|
||||
req.PeerID = pid.String()
|
||||
} else if _, err := uuid.Parse(needle); err == nil {
|
||||
@@ -238,7 +220,6 @@ func (d *Node) SearchPeerRecord(userKey, needle string, onResult func(common.Sea
|
||||
req.Name = needle
|
||||
}
|
||||
|
||||
// Try indexers in pool order until one accepts the stream.
|
||||
for _, ad := range common.Indexers.GetAddrs() {
|
||||
if ad.Info == nil {
|
||||
continue
|
||||
@@ -253,15 +234,22 @@ func (d *Node) SearchPeerRecord(userKey, needle string, onResult func(common.Sea
|
||||
s.Reset()
|
||||
continue
|
||||
}
|
||||
// Interrupt the blocking Decode as soon as the context is cancelled
|
||||
// (idle timer, explicit PB_CLOSE_SEARCH, or replacement search).
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
s.SetReadDeadline(time.Now())
|
||||
}()
|
||||
dec := json.NewDecoder(s)
|
||||
for {
|
||||
var result common.SearchPeerResult
|
||||
if err := dec.Decode(&result); err != nil {
|
||||
break
|
||||
}
|
||||
if result.QueryID != queryID {
|
||||
continue // stale response from a previous query
|
||||
if result.QueryID != searchKey || !d.peerSearches.IsActive(searchKey) {
|
||||
break
|
||||
}
|
||||
d.peerSearches.ResetIdle(searchKey)
|
||||
for _, hit := range result.Records {
|
||||
onResult(hit)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user