merged from gramsrv upstream

This commit is contained in:
onysd 2026-09-01 12:06:31 +03:00
parent 79c64ee916
commit 21a0856587
651 changed files with 54774 additions and 4590 deletions

109
cmd/telesrv-update/main.go Normal file
View file

@ -0,0 +1,109 @@
// Command telesrv-update serves native Telegram client update metadata and
// immutable, range-enabled desktop update packages.
package main
import (
"context"
"errors"
"flag"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"go.uber.org/zap"
"telesrv/internal/updatecdn"
)
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, "telesrv-update:", err)
os.Exit(1)
}
}
func run() error {
listenDefault := envOr("TELESRV_UPDATE_LISTEN", "127.0.0.1:2402")
manifestDefault := envOr("TELESRV_UPDATE_MANIFEST", "data/updates/manifest.json")
filesDefault := envOr("TELESRV_UPDATE_FILES_DIR", "data/updates/files")
listenAddr := flag.String("listen", listenDefault, "HTTP listen address")
manifestPath := flag.String("manifest", manifestDefault, "release manifest path")
filesDir := flag.String("files", filesDefault, "desktop update package directory")
check := flag.Bool("check", false, "validate the catalog and exit")
flag.Parse()
store, err := updatecdn.NewStore(*manifestPath, *filesDir)
if err != nil {
return fmt.Errorf("load update catalog: %w", err)
}
if *check {
fmt.Println("update catalog is valid")
return nil
}
handler, err := updatecdn.NewHandler(store)
if err != nil {
return err
}
listener, err := net.Listen("tcp", *listenAddr)
if err != nil {
return fmt.Errorf("listen on %s: %w", *listenAddr, err)
}
logger, err := zap.NewProduction()
if err != nil {
_ = listener.Close()
return fmt.Errorf("initialize logger: %w", err)
}
defer logger.Sync() //nolint:errcheck
server := &http.Server{
Handler: handler,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 5 * time.Minute,
IdleTimeout: 2 * time.Minute,
MaxHeaderBytes: 32 << 10,
}
serveErr := make(chan error, 1)
go func() {
serveErr <- server.Serve(listener)
}()
logger.Info("update service started",
zap.String("listen", listener.Addr().String()),
zap.String("manifest", *manifestPath),
zap.String("files", *filesDir))
stopCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
select {
case err := <-serveErr:
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return fmt.Errorf("serve HTTP: %w", err)
case <-stopCtx.Done():
}
shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
return fmt.Errorf("shutdown HTTP server: %w", err)
}
if err := <-serveErr; err != nil && !errors.Is(err, http.ErrServerClosed) {
return fmt.Errorf("serve HTTP: %w", err)
}
logger.Info("update service stopped")
return nil
}
func envOr(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok && value != "" {
return value
}
return fallback
}