Skip to content
Open
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
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "go.mod|go.sum|^.secrets.baseline$",
"lines": null
},
"generated_at": "2026-05-26T06:43:32Z",
"generated_at": "2026-07-09T04:46:34Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -332,7 +332,7 @@
"hashed_secret": "6947818ac409551f11fbaa78f0ea6391960aa5b8",
"is_secret": false,
"is_verified": false,
"line_number": 121,
"line_number": 124,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
55 changes: 51 additions & 4 deletions api/cmd/pac-go-server/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package main

import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"

flag "github.com/spf13/pflag"
Expand All @@ -20,6 +25,12 @@ var (
servicePort = "8000"
)

// shutdownGrace is the time the server gives active WebSocket sessions and
// background workers to finish before the process exits. Long enough for
// in-flight DB writes and a clean WS close frame; short enough to satisfy
// most orchestrator restart budgets (Kubernetes default terminationGracePeriodSeconds=30s).
const shutdownGrace = 10 * time.Second

func initFlags() {
flag.StringVar(&servicePort, "port", "8000", "port to run the service on")
flag.StringSliceVar(&models.ExcludeGroups, "exclude-groups", []string{"admin"}, "comma separated list of groups to exclude")
Expand All @@ -42,7 +53,7 @@ func main() {

defer func() {
if err := db.Disconnect(); err != nil {
panic(err)
logger.Error("failed to disconnect from MongoDB", zap.Error(err))
}
}()
services.SetDB(db)
Expand All @@ -54,7 +65,43 @@ func main() {
logger.Info("Starting service expiry notifier")
go services.ExpiryNotification()

var appRouter = router.CreateRouter()
logger.Info("PAC server is up and running", zap.String("port", servicePort))
logger.Fatal("Error encountered while routing", zap.Error(appRouter.Run(":"+servicePort)))
// workerCtx is cancelled on shutdown to signal the background worker to
// drain its queue and exit.
workerCtx, workerCancel := context.WithCancel(context.Background())
go services.StartAdminReplyWorker(workerCtx)

srv := &http.Server{
Addr: ":" + servicePort,
Handler: router.CreateRouter(),
}

// Start serving in a background goroutine so the main goroutine can block
// on the OS signal channel instead.
go func() {
logger.Info("PAC server is up and running", zap.String("port", servicePort))
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Fatal("server error", zap.Error(err))
}
}()

// Block until SIGINT or SIGTERM is received.
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
sig := <-quit
logger.Info("shutdown signal received, draining active connections",
zap.String("signal", sig.String()),
zap.Duration("grace", shutdownGrace),
)

// Stop accepting new connections; give existing sessions the grace period.
shutCtx, shutCancel := context.WithTimeout(context.Background(), shutdownGrace)
defer shutCancel()
if err := srv.Shutdown(shutCtx); err != nil {
logger.Error("server forced to shut down before grace period expired", zap.Error(err))
}

// Cancel the worker context so StartAdminReplyWorker drains and exits.
workerCancel()

logger.Info("PAC server exited cleanly")
}
1 change: 1 addition & 0 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/IBM/platform-services-go-sdk v0.89.0
github.com/IBM/vpc-go-sdk v0.74.1
github.com/Nerzal/gocloak/v13 v13.9.0
github.com/coder/websocket v1.8.15
github.com/gin-gonic/gin v1.11.0
github.com/go-logr/logr v1.4.3
github.com/go-playground/validator/v10 v10.28.0
Expand Down
2 changes: 2 additions & 0 deletions api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gE
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA=
github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0=
github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=
Expand Down
11 changes: 11 additions & 0 deletions api/internal/pkg/pac-go-server/db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,15 @@ type DB interface {
CreateMaintenanceWindow(window *models.MaintenanceWindow) error
UpdateMaintenanceWindow(window *models.MaintenanceWindow) error
DeleteMaintenanceWindow(id string, deletedBy string, deletedAt *time.Time) error

// Chat support operations
InsertChatMessage(msg *models.ChatMessage) error
MarkConversationEnded(ctx context.Context, userID, username string, conversationID int64) error
IsConversationEnded(ctx context.Context, userID string, conversationID int64) (bool, error)
GetCurrentConversationID(ctx context.Context, userID string) (int64, error)
GetNextConversationID(ctx context.Context, userID string) (int64, error)
GetChatMessages(ctx context.Context, userID string, conversationID int64) ([]models.ChatMessage, error)
GetUserConversations(ctx context.Context, userID string) ([]models.ConversationSummary, error)
GetAllConversations(ctx context.Context) ([]models.ConversationSummary, error)
AdminReplyToConversation(ctx context.Context, msg *models.ChatMessage) error
}
133 changes: 133 additions & 0 deletions api/internal/pkg/pac-go-server/db/mock_db_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading