@@ -3,37 +3,86 @@ package main
33import (
44 "context"
55 "errors"
6+ "fmt"
67 "log/slog"
78 "net/http"
89 "os"
910 "os/signal"
1011 "syscall"
1112 "time"
1213
14+ "github.com/KB01111/A2A-RedPandaServer-Container/internal/auth"
1315 "github.com/KB01111/A2A-RedPandaServer-Container/internal/config"
1416 "github.com/KB01111/A2A-RedPandaServer-Container/internal/orchestrator"
1517 appserver "github.com/KB01111/A2A-RedPandaServer-Container/internal/server"
18+ "github.com/KB01111/A2A-RedPandaServer-Container/internal/storage/postgres"
1619)
1720
1821func main () {
1922 logger := slog .New (slog .NewJSONHandler (os .Stdout , nil ))
23+ if err := run (logger ); err != nil {
24+ logger .Error ("server failed" , "error" , err )
25+ os .Exit (1 )
26+ }
27+ }
28+
29+ func run (logger * slog.Logger ) error {
2030 cfg , err := config .Load ()
2131 if err != nil {
22- logger .Error ("invalid configuration" , "error" , err )
23- os .Exit (1 )
32+ return fmt .Errorf ("invalid configuration: %w" , err )
2433 }
2534 if cfg .Environment != "development" && cfg .Environment != "test" {
26- logger .Error ("production dependencies are not configured" , "environment" , cfg .Environment )
27- os .Exit (1 )
35+ return fmt .Errorf ("redpanda dispatcher is not configured for %s" , cfg .Environment )
2836 }
2937
30- handler , err := appserver .New (cfg , appserver.Dependencies {
38+ shutdownSignals , stop := signal .NotifyContext (context .Background (), syscall .SIGINT , syscall .SIGTERM )
39+ defer stop ()
40+
41+ dependencies := appserver.Dependencies {
3142 Dispatcher : orchestrator.LoopbackDispatcher {},
3243 Logger : logger ,
33- })
44+ }
45+ if cfg .OIDC .Enabled () {
46+ verifier , err := auth .NewOIDCVerifier (shutdownSignals , cfg .OIDC )
47+ if err != nil {
48+ return fmt .Errorf ("initialize OIDC verifier: %w" , err )
49+ }
50+ dependencies .Authentication , err = auth .NewAuthenticator (verifier , cfg .OIDC .Issuer , cfg .OIDC .RequiredScopes )
51+ if err != nil {
52+ return fmt .Errorf ("initialize authentication: %w" , err )
53+ }
54+ }
55+
56+ if cfg .Database .URL != "" {
57+ if dependencies .Authentication == nil {
58+ return fmt .Errorf ("DATABASE_URL requires OIDC authentication" )
59+ }
60+ pool , err := postgres .OpenPool (shutdownSignals , postgres.PoolConfig {
61+ DatabaseURL : cfg .Database .URL ,
62+ PasswordFile : cfg .Database .PasswordFile ,
63+ ApplicationName : "bridge-a2a-server" ,
64+ MaxConns : cfg .Database .MaxConnections ,
65+ MinConns : cfg .Database .MinConnections ,
66+ MaxConnLifetime : cfg .Database .MaxConnectionLife ,
67+ MaxConnIdleTime : cfg .Database .MaxConnectionIdle ,
68+ HealthCheckPeriod : cfg .Database .HealthCheckPeriod ,
69+ })
70+ if err != nil {
71+ return err
72+ }
73+ defer pool .Close ()
74+ if err := postgres .VerifySchema (shutdownSignals , pool ); err != nil {
75+ return fmt .Errorf ("verify database schema: %w" , err )
76+ }
77+ dependencies .TaskStore , err = postgres .NewStore (pool )
78+ if err != nil {
79+ return err
80+ }
81+ }
82+
83+ handler , err := appserver .New (cfg , dependencies )
3484 if err != nil {
35- logger .Error ("build server" , "error" , err )
36- os .Exit (1 )
85+ return fmt .Errorf ("build server: %w" , err )
3786 }
3887
3988 server := & http.Server {
@@ -45,8 +94,6 @@ func main() {
4594 MaxHeaderBytes : 1 << 20 ,
4695 }
4796
48- shutdownSignals , stop := signal .NotifyContext (context .Background (), syscall .SIGINT , syscall .SIGTERM )
49- defer stop ()
5097 go func () {
5198 <- shutdownSignals .Done ()
5299 ctx , cancel := context .WithTimeout (context .Background (), cfg .ShutdownTimeout )
@@ -58,7 +105,7 @@ func main() {
58105
59106 logger .Info ("starting A2A server" , "address" , server .Addr , "environment" , cfg .Environment )
60107 if err := server .ListenAndServe (); err != nil && ! errors .Is (err , http .ErrServerClosed ) {
61- logger .Error ("server stopped" , "error" , err )
62- os .Exit (1 )
108+ return fmt .Errorf ("serve HTTP: %w" , err )
63109 }
110+ return nil
64111}
0 commit comments