feat(worker): adopt canonical public URL
Все проверки выполнены успешно
CI / test (push) Successful in 10m15s
Docker / Build and publish worker image (push) Successful in 34m59s
Все проверки выполнены успешно
CI / test (push) Successful in 10m15s
Docker / Build and publish worker image (push) Successful in 34m59s
Этот коммит содержится в:
@@ -4,10 +4,15 @@ package wire
|
||||
import "encoding/json"
|
||||
|
||||
// RegisterRequest is sent to the control plane registration API.
|
||||
// PublicURL is the canonical advertised origin (scheme and authority
|
||||
// only, see docs/public-endpoint-and-identity.md). The legacy URL field
|
||||
// remains on the wire for the bounded migration from WORKER_URL; new
|
||||
// senders populate PublicURL and old control planes keep reading URL.
|
||||
type RegisterRequest struct {
|
||||
WorkerID string `json:"worker_id" binding:"required"`
|
||||
RegionCode string `json:"region_code" binding:"required"`
|
||||
Version string `json:"version"`
|
||||
PublicURL string `json:"public_url,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
TaskEnvelope bool `json:"task_envelope"`
|
||||
@@ -203,6 +208,9 @@ type PeerInfo struct {
|
||||
}
|
||||
|
||||
// WorkerInit is sent by the control plane after websocket authentication.
|
||||
// PublicURL is the canonical advertised origin accepted by the control
|
||||
// plane; URL is the legacy wire field kept for the bounded migration.
|
||||
// A worker must prefer PublicURL when it is non-empty.
|
||||
type WorkerInit struct {
|
||||
WorkerID string `json:"worker_id"`
|
||||
RegionCode string `json:"region_code"`
|
||||
@@ -211,6 +219,7 @@ type WorkerInit struct {
|
||||
NotificationMethods []string `json:"notification_methods,omitempty"`
|
||||
NotificationAccounts []int64 `json:"notification_accounts,omitempty"`
|
||||
Concurrency int `json:"concurrency"`
|
||||
PublicURL string `json:"public_url,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
ServerID *int64 `json:"server_id,omitempty"`
|
||||
LLMs []LLMConfig `json:"llms,omitempty"`
|
||||
|
||||
@@ -151,6 +151,82 @@ func TestRegisterRequest_URLOmittedWhenEmpty(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.False(t, strings.Contains(string(data), `"url"`),
|
||||
"empty URL must be omitted from the register payload, got %s", string(data))
|
||||
assert.False(t, strings.Contains(string(data), `"public_url"`),
|
||||
"empty PublicURL must be omitted from the register payload, got %s", string(data))
|
||||
}
|
||||
|
||||
// TestRegisterRequest_PublicURLRoundTrip verifies the canonical public_url
|
||||
// wire field serializes and deserializes alongside the legacy url field.
|
||||
func TestRegisterRequest_PublicURLRoundTrip(t *testing.T) {
|
||||
req := RegisterRequest{
|
||||
WorkerID: "worker-eu-1",
|
||||
RegionCode: "eu",
|
||||
Version: "v1",
|
||||
PublicURL: "https://worker-eu.example.com",
|
||||
}
|
||||
|
||||
data, err := json.Marshal(req)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(data), `"public_url":"https://worker-eu.example.com"`,
|
||||
"PublicURL must serialize as the top-level public_url field, got %s", string(data))
|
||||
|
||||
var decoded RegisterRequest
|
||||
require.NoError(t, json.Unmarshal(data, &decoded))
|
||||
assert.Equal(t, "https://worker-eu.example.com", decoded.PublicURL)
|
||||
}
|
||||
|
||||
// TestWorkerInit_PublicURLRoundTrip covers the canonical public_url field
|
||||
// on the init/config frame.
|
||||
func TestWorkerInit_PublicURLRoundTrip(t *testing.T) {
|
||||
init := WorkerInit{
|
||||
WorkerID: "worker-1",
|
||||
RegionCode: "ru",
|
||||
Version: "v1",
|
||||
Concurrency: 4,
|
||||
PublicURL: "https://worker-eu.example.com",
|
||||
}
|
||||
|
||||
data, err := json.Marshal(init)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(data), `"public_url":"https://worker-eu.example.com"`,
|
||||
"PublicURL must serialize as a top-level public_url field, got %s", string(data))
|
||||
|
||||
var decoded WorkerInit
|
||||
require.NoError(t, json.Unmarshal(data, &decoded))
|
||||
assert.Equal(t, "https://worker-eu.example.com", decoded.PublicURL)
|
||||
assert.Equal(t, "", decoded.URL,
|
||||
"legacy URL field must stay empty when only public_url is set")
|
||||
}
|
||||
|
||||
// TestWorkerInit_LegacyURLFieldStillDecodes keeps the bounded-migration
|
||||
// contract: a control plane that still sends the legacy url field must
|
||||
// remain wire-compatible with the new worker struct.
|
||||
func TestWorkerInit_LegacyURLFieldStillDecodes(t *testing.T) {
|
||||
data := []byte(`{"worker_id":"worker-1","region_code":"ru","concurrency":4,"url":"https://legacy.example.com"}`)
|
||||
var decoded WorkerInit
|
||||
require.NoError(t, json.Unmarshal(data, &decoded))
|
||||
assert.Equal(t, "https://legacy.example.com", decoded.URL)
|
||||
assert.Equal(t, "", decoded.PublicURL)
|
||||
}
|
||||
|
||||
// TestWorkerInit_PublicURLAndLegacyCoexist ensures a frame that carries
|
||||
// both fields keeps both on the wire for old and new control planes.
|
||||
func TestWorkerInit_PublicURLAndLegacyCoexist(t *testing.T) {
|
||||
init := WorkerInit{
|
||||
WorkerID: "w-1",
|
||||
PublicURL: "https://canonical.example.com",
|
||||
URL: "https://legacy.example.com",
|
||||
}
|
||||
data, err := json.Marshal(init)
|
||||
require.NoError(t, err)
|
||||
out := string(data)
|
||||
assert.Contains(t, out, `"public_url":"https://canonical.example.com"`)
|
||||
assert.Contains(t, out, `"url":"https://legacy.example.com"`)
|
||||
|
||||
var decoded WorkerInit
|
||||
require.NoError(t, json.Unmarshal(data, &decoded))
|
||||
assert.Equal(t, "https://canonical.example.com", decoded.PublicURL)
|
||||
assert.Equal(t, "https://legacy.example.com", decoded.URL)
|
||||
}
|
||||
|
||||
// TestWorkerInit_NotificationCapabilitiesRoundTrip ensures the
|
||||
|
||||
Ссылка в новой задаче
Block a user