package main import ( "encoding/json" "fmt" "log" "time" ) var forumResultsChan = make(chan []ForumSearchResult) func tryOtherNodesForForumSearch(query, safe, lang string, page int) []ForumSearchResult { for _, nodeAddr := range peers { results, err := sendForumSearchRequestToNode(nodeAddr, query, safe, lang, page, []string{}) if err != nil { log.Printf("Error contacting node %s: %v", nodeAddr, err) continue } if len(results) > 0 { return results } } return nil } func sendForumSearchRequestToNode(nodeAddr, query, safe, lang string, page int, visitedNodes []string) ([]ForumSearchResult, error) { // Check if the current node has already been visited for _, node := range visitedNodes { if node == hostID { return nil, fmt.Errorf("loop detected: this node (%s) has already been visited", hostID) } } // Add current node to the list of visited nodes visitedNodes = append(visitedNodes, hostID) searchParams := struct { Query string `json:"query"` Safe string `json:"safe"` Lang string `json:"lang"` Page int `json:"page"` ResponseAddr string `json:"responseAddr"` VisitedNodes []string `json:"visitedNodes"` }{ Query: query, Safe: safe, Lang: lang, Page: page, ResponseAddr: fmt.Sprintf("http://localhost:%d/node", config.Port), VisitedNodes: visitedNodes, } msgBytes, err := json.Marshal(searchParams) if err != nil { return nil, fmt.Errorf("failed to marshal search parameters: %v", err) } msg := Message{ ID: hostID, Type: "search-forum", Content: string(msgBytes), } err = sendMessage(nodeAddr, msg) if err != nil { return nil, fmt.Errorf("failed to send search request to node %s: %v", nodeAddr, err) } // Wait for results select { case res := <-forumResultsChan: return res, nil case <-time.After(20 * time.Second): return nil, fmt.Errorf("timeout waiting for results from node %s", nodeAddr) } } func handleForumResultsMessage(msg Message) { var results []ForumSearchResult err := json.Unmarshal([]byte(msg.Content), &results) if err != nil { log.Printf("Error unmarshalling forum results: %v", err) return } log.Printf("Received forum results: %+v", results) // Send results to forumResultsChan go func() { forumResultsChan <- results }() } // Used only to answer requests func fetchForumResults(query, safe, lang string, page int) []ForumSearchResult { results, err := PerformRedditSearch(query, safe, page) if err != nil { log.Printf("Error fetching forum results: %v", err) return nil } return results }