Memby v0.1.53: Android TV client plus gateway
Android TV client for Emby (Kotlin, Compose for TV) and the Memby gateway (Go, Postgres, Redis) that fronts it. Client: - Setup, profiles, home rows, Media3 playback, system screensaver (Dream) - Backend chosen at build time: gateway when memby.gatewayUrl is set, otherwise direct to Emby. Both paths stay working. - Server-composed home rows, rendered verbatim so new row types ship without an app release - Full-screen animated maintenance state, row engagement telemetry Gateway: - One request per TV screen; auth, caching, search and row shaping - Library import from Emby into Postgres (manual, then hourly incremental) - Recommendations from viewing history (recency-weighted genre affinity) - Admin page for imports, an offline switch, and per-row analytics - Video always direct-plays from Emby; only metadata passes through Identity is com.ponzischeme89.memby throughout, replacing com.mattcohen.embyclientsname. A changed applicationId installs as a new app: TVs need a fresh sign-in and the old package uninstalled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func hexHash(hash []byte) string { return hex.EncodeToString(hash) }
|
||||
|
||||
// handleHealth is liveness: the process is up. It touches no dependency, so an
|
||||
// orchestrator does not restart the container just because Emby is down.
|
||||
func (s *Server) handleHealth(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
// handleReady is readiness: everything this service needs is reachable.
|
||||
func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
checks := map[string]string{}
|
||||
status := http.StatusOK
|
||||
|
||||
if err := s.store.Ping(ctx); err != nil {
|
||||
checks["postgres"] = err.Error()
|
||||
status = http.StatusServiceUnavailable
|
||||
} else {
|
||||
checks["postgres"] = "ok"
|
||||
}
|
||||
|
||||
if err := s.cache.Ping(ctx); err != nil {
|
||||
checks["redis"] = err.Error()
|
||||
status = http.StatusServiceUnavailable
|
||||
} else {
|
||||
checks["redis"] = "ok"
|
||||
}
|
||||
|
||||
// Emby being unreachable is reported but does not fail readiness: cached responses
|
||||
// are still worth serving, and flapping the container would not bring Emby back.
|
||||
if err := s.emby.Ping(ctx); err != nil {
|
||||
checks["emby"] = err.Error()
|
||||
} else {
|
||||
checks["emby"] = "ok"
|
||||
}
|
||||
|
||||
writeJSON(w, status, checks)
|
||||
}
|
||||
Reference in New Issue
Block a user