Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions handshake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package main

import (
"net/http"
"runtime/debug"
"sync"
)

const (
clientName = "schematic-datastream-replicator"
clientModulePath = "github.com/schematichq/schematic-datastream-replicator"
)

var (
clientVersionOnce sync.Once
clientVersion string
)

// ClientVersion returns the replicator version reported on the DataStream
// handshake. It prefers the ldflag-injected `main.version` used by the
// Dockerfile build, then falls back to module build info (a tag for
// `go install …@v1.2.3` builds, "(devel)" for local `go build .`), and
// finally "unknown".
func ClientVersion() string {
clientVersionOnce.Do(func() {
clientVersion = resolveClientVersion()
})
return clientVersion
}

func resolveClientVersion() string {
if version != "" {
return version
}
info, ok := debug.ReadBuildInfo()
if !ok {
return "unknown"
}
if info.Main.Path == clientModulePath && info.Main.Version != "" {
return info.Main.Version
}
for _, dep := range info.Deps {
if dep == nil || dep.Path != clientModulePath {
continue
}
if dep.Replace != nil && dep.Replace.Version != "" {
return dep.Replace.Version
}
if dep.Version != "" {
return dep.Version
}
}
return "unknown"
}

// datastreamHandshakeHeaders returns the HTTP headers attached to the
// outbound DataStream WebSocket handshake so the backend can distinguish
// replicator connections from direct-SDK connections and correlate them to a
// release.
func datastreamHandshakeHeaders() http.Header {
h := http.Header{}
h.Set("X-Schematic-Datastream-Mode", "replicator")
h.Set("X-Schematic-Client", clientName)
h.Set("X-Schematic-Client-Version", ClientVersion())
return h
}
16 changes: 16 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ import (
"github.com/schematichq/schematic-go/option"
)

// Populated at build time via -ldflags="-X main.version=... -X main.commit=... -X main.buildTime=..."
var (
version string
commit string
buildTime string
)

func valueOrUnknown(s string) string {
if s == "" {
return "unknown"
}
return s
}

const (
defaultAPIURL = "https://api.schematichq.com"
apiKeyEnvVar = "SCHEMATIC_API_KEY"
Expand Down Expand Up @@ -286,6 +300,7 @@ func main() {
MaxReconnectAttempts: 10,
MinReconnectDelay: 1 * time.Second,
MaxReconnectDelay: 30 * time.Second,
ExtraHeaders: datastreamHandshakeHeaders(),
}

// Get WebSocket ping/pong intervals from environment (optional)
Expand All @@ -309,6 +324,7 @@ func main() {
}

logger.Info(context.Background(), "Starting Schematic Datastream Replicator...")
logger.Info(context.Background(), fmt.Sprintf("Version: %s, Commit: %s, Build time: %s", ClientVersion(), valueOrUnknown(commit), valueOrUnknown(buildTime)))
logger.Info(context.Background(), fmt.Sprintf("API URL: %s", apiBaseURL))
if os.Getenv("SCHEMATIC_DATASTREAM_URL") != "" {
logger.Info(context.Background(), fmt.Sprintf("Datastream URL: %s (explicit)", datastreamURL))
Expand Down