mirror of
https://github.com/benbusby/farside.git
synced 2025-03-14 11:16:34 -04:00

Some checks are pending
Tests / test (1.21.x, macos-latest) (push) Waiting to run
Tests / test (1.21.x, ubuntu-latest) (push) Waiting to run
Tests / test (1.21.x, windows-latest) (push) Waiting to run
Tests / test (1.22.x, macos-latest) (push) Waiting to run
Tests / test (1.22.x, ubuntu-latest) (push) Waiting to run
Tests / test (1.22.x, windows-latest) (push) Waiting to run
Tests / test (1.23.x, macos-latest) (push) Waiting to run
Tests / test (1.23.x, ubuntu-latest) (push) Waiting to run
Tests / test (1.23.x, windows-latest) (push) Waiting to run
Services like searxng don't need to have instance checks performed since the nightly cron task filters out the instances already.
154 lines
3.2 KiB
Go
154 lines
3.2 KiB
Go
package db
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/benbusby/farside/services"
|
|
"github.com/robfig/cron/v3"
|
|
)
|
|
|
|
const defaultPrimary = "https://farside.link/state"
|
|
const defaultCFPrimary = "https://cf.farside.link/state"
|
|
|
|
var LastUpdate time.Time
|
|
var skipInstanceChecks = []string{
|
|
"searx",
|
|
"searxng",
|
|
}
|
|
|
|
func InitCronTasks() {
|
|
log.Println("Initializing cron tasks...")
|
|
updateServiceList()
|
|
|
|
cronDisabled := os.Getenv("FARSIDE_CRON")
|
|
if len(cronDisabled) == 0 || cronDisabled == "1" {
|
|
c := cron.New()
|
|
c.AddFunc("@every 10m", queryServiceInstances)
|
|
c.AddFunc("@daily", updateServiceList)
|
|
c.Start()
|
|
}
|
|
|
|
queryServiceInstances()
|
|
}
|
|
|
|
func updateServiceList() {
|
|
fileName := services.GetServicesFileName()
|
|
_, _ = services.FetchServicesFile(fileName)
|
|
services.InitializeServices()
|
|
}
|
|
|
|
func queryServiceInstances() {
|
|
log.Println("Starting instance queries...")
|
|
|
|
isPrimary := os.Getenv("FARSIDE_PRIMARY")
|
|
if len(isPrimary) == 0 || isPrimary != "1" {
|
|
remoteServices, err := fetchInstancesFromPrimary()
|
|
if err != nil {
|
|
log.Println("Unable to fetch instances from primary", err)
|
|
}
|
|
|
|
for _, service := range remoteServices {
|
|
SetInstances(service.Type, service.Instances)
|
|
}
|
|
|
|
LastUpdate = time.Now().UTC()
|
|
return
|
|
}
|
|
|
|
for _, service := range services.ServiceList {
|
|
canSkip := slices.Contains[[]string, string](skipInstanceChecks, service.Type)
|
|
|
|
fmt.Printf("===== %s =====\n", service.Type)
|
|
var instances []string
|
|
for _, instance := range service.Instances {
|
|
testURL := strings.ReplaceAll(
|
|
service.TestURL,
|
|
"<%=query%>",
|
|
"current+weather")
|
|
available := queryServiceInstance(
|
|
instance,
|
|
testURL,
|
|
canSkip)
|
|
|
|
if available {
|
|
instances = append(instances, instance)
|
|
}
|
|
}
|
|
|
|
SetInstances(service.Type, instances)
|
|
}
|
|
|
|
LastUpdate = time.Now().UTC()
|
|
}
|
|
|
|
func fetchInstancesFromPrimary() ([]services.Service, error) {
|
|
primaryURL := defaultPrimary
|
|
useCF := os.Getenv("FARSIDE_CF_ENABLED")
|
|
if len(useCF) > 0 && useCF == "1" {
|
|
primaryURL = defaultCFPrimary
|
|
}
|
|
|
|
resp, err := http.Get(primaryURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var serviceList []services.Service
|
|
err = json.Unmarshal(bodyBytes, &serviceList)
|
|
return serviceList, err
|
|
}
|
|
|
|
func queryServiceInstance(instance, testURL string, canSkipCheck bool) bool {
|
|
testMode := os.Getenv("FARSIDE_TEST")
|
|
if len(testMode) > 0 && testMode == "1" {
|
|
return true
|
|
}
|
|
|
|
if canSkipCheck {
|
|
fmt.Printf(" [INFO] Adding %s\n", instance)
|
|
return true
|
|
}
|
|
|
|
ua := "Mozilla/5.0 (compatible; Farside/1.0.0; +https://farside.link)"
|
|
url := instance + testURL
|
|
|
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
if err != nil {
|
|
fmt.Println(" [ERRO] Failed to create new http request!", err)
|
|
return false
|
|
}
|
|
|
|
req.Header.Set("User-Agent", ua)
|
|
client := &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
}
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
fmt.Println(" [ERRO] Error fetching instance:", err)
|
|
return false
|
|
} else if resp.StatusCode != http.StatusOK {
|
|
fmt.Printf(" [WARN] Received non-200 status for %s\n", url)
|
|
return false
|
|
} else {
|
|
fmt.Printf(" [INFO] Received 200 status for %s\n", url)
|
|
}
|
|
|
|
return true
|
|
}
|