Spaces:
Runtime error
Runtime error
| // Package controlplane holds the (mostly designed, partly stubbed) outbound | |
| // connection from matrix-runtime to MatrixHub Cloud. In the hybrid model the | |
| // runtime lives in customer infrastructure and dials out to the cloud control | |
| // plane, so no inbound firewall exposure is required. | |
| package controlplane | |
| import ( | |
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "net/http" | |
| "strings" | |
| "time" | |
| ) | |
| // Client talks to MatrixHub Cloud over outbound HTTPS. | |
| type Client struct { | |
| CloudURL string | |
| JoinToken string | |
| RuntimeID string | |
| Workspace string | |
| HTTP *http.Client | |
| } | |
| // New builds a control-plane client. | |
| func New(cloudURL, joinToken, runtimeID, workspace string) *Client { | |
| return &Client{ | |
| CloudURL: strings.TrimRight(cloudURL, "/"), | |
| JoinToken: joinToken, | |
| RuntimeID: runtimeID, | |
| Workspace: workspace, | |
| HTTP: &http.Client{Timeout: 30 * time.Second}, | |
| } | |
| } | |
| // Heartbeat reports liveness to the cloud. Stubbed: it performs a single | |
| // authenticated POST to /v1/runtimes/heartbeat and tolerates absence of the | |
| // endpoint, since the MVP runs primarily via the direct HTTP API. | |
| func (c *Client) Heartbeat(ctx context.Context, capabilities any) error { | |
| if c.CloudURL == "" || c.JoinToken == "" { | |
| return fmt.Errorf("control plane not configured") | |
| } | |
| body, _ := json.Marshal(map[string]any{ | |
| "runtime_id": c.RuntimeID, | |
| "workspace": c.Workspace, | |
| "capabilities": capabilities, | |
| }) | |
| req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.CloudURL+"/v1/runtimes/heartbeat", strings.NewReader(string(body))) | |
| if err != nil { | |
| return err | |
| } | |
| req.Header.Set("Authorization", "Bearer "+c.JoinToken) | |
| req.Header.Set("Content-Type", "application/json") | |
| resp, err := c.HTTP.Do(req) | |
| if err != nil { | |
| return err | |
| } | |
| defer func() { _ = resp.Body.Close() }() | |
| if resp.StatusCode >= 400 { | |
| return fmt.Errorf("heartbeat rejected: status %d", resp.StatusCode) | |
| } | |
| return nil | |
| } | |