github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/scrape/notify.go (about)

     1  package scrapePkg
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"net/http"
    10  	"strings"
    11  	"syscall"
    12  
    13  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    14  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/notify"
    15  )
    16  
    17  var ErrConfiguredButNotRunning = fmt.Errorf("listener is configured but not running")
    18  
    19  // GetNotifyEndpoint returns the notification endpoint
    20  func GetNotifyEndpoint() string {
    21  	endpoint := config.GetSettings().Notify.Url
    22  	// If protocol is not specified, use http by default
    23  	if endpoint != "" && !strings.HasPrefix(endpoint, "http") {
    24  		endpoint = "http://" + endpoint
    25  	}
    26  	return endpoint
    27  }
    28  
    29  // NotifyConfigured returns true if notification feature is configured
    30  func NotifyConfigured() bool {
    31  	return GetNotifyEndpoint() != ""
    32  }
    33  
    34  // Notify may be used to tell other processes about progress.
    35  func Notify[T notify.NotificationPayload](notification notify.Notification[T]) error {
    36  	endpoint := GetNotifyEndpoint()
    37  	if endpoint == "" {
    38  		return nil
    39  	}
    40  	return notifyEndpoint(endpoint, notification)
    41  }
    42  
    43  func notifyEndpoint(endpoint string, notification any) error {
    44  	encoded, err := json.Marshal(notification)
    45  	if err != nil {
    46  		return fmt.Errorf("marshalling message: %w", err)
    47  	}
    48  
    49  	resp, err := http.Post(
    50  		endpoint,
    51  		"application/json",
    52  		bytes.NewReader(encoded),
    53  	)
    54  
    55  	if err != nil {
    56  		if errors.Is(err, syscall.ECONNREFUSED) {
    57  			return ErrConfiguredButNotRunning
    58  		}
    59  		return fmt.Errorf("sending notification: %w", err)
    60  	}
    61  	if resp.StatusCode < 200 || resp.StatusCode > 299 {
    62  		respBody, _ := io.ReadAll(resp.Body)
    63  		resp.Body.Close()
    64  		return fmt.Errorf("listener responded with %d: %s", resp.StatusCode, respBody)
    65  	}
    66  	return nil
    67  }