@@ -25,6 +25,7 @@ import (
2525
2626 "github.com/NdoleStudio/httpsms/pkg/discord"
2727
28+ "cloud.google.com/go/storage"
2829 mexporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric"
2930 cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
3031 "github.com/NdoleStudio/httpsms/pkg/cache"
@@ -80,13 +81,14 @@ import (
8081
8182// Container is used to resolve services at runtime
8283type Container struct {
83- projectID string
84- db * gorm.DB
85- dedicatedDB * gorm.DB
86- version string
87- app * fiber.App
88- eventDispatcher * services.EventDispatcher
89- logger telemetry.Logger
84+ projectID string
85+ db * gorm.DB
86+ dedicatedDB * gorm.DB
87+ version string
88+ app * fiber.App
89+ eventDispatcher * services.EventDispatcher
90+ logger telemetry.Logger
91+ attachmentStorage repositories.AttachmentStorage
9092}
9193
9294// NewLiteContainer creates a Container without any routes or listeners
@@ -118,6 +120,7 @@ func NewContainer(projectID string, version string) (container *Container) {
118120
119121 container .RegisterMessageListeners ()
120122 container .RegisterMessageRoutes ()
123+ container .RegisterAttachmentRoutes ()
121124 container .RegisterBulkMessageRoutes ()
122125
123126 container .RegisterMessageThreadRoutes ()
@@ -1430,9 +1433,63 @@ func (container *Container) MessageService() (service *services.MessageService)
14301433 container .MessageRepository (),
14311434 container .EventDispatcher (),
14321435 container .PhoneService (),
1436+ container .AttachmentStorage (),
1437+ container .APIBaseURL (),
14331438 )
14341439}
14351440
1441+ // AttachmentStorage creates a cached AttachmentStorage based on configuration
1442+ func (container * Container ) AttachmentStorage () repositories.AttachmentStorage {
1443+ if container .attachmentStorage != nil {
1444+ return container .attachmentStorage
1445+ }
1446+
1447+ bucket := os .Getenv ("GCS_BUCKET_NAME" )
1448+ if bucket != "" {
1449+ container .logger .Debug ("creating GCSAttachmentStorage" )
1450+ client , err := storage .NewClient (context .Background ())
1451+ if err != nil {
1452+ container .logger .Fatal (stacktrace .Propagate (err , "cannot create GCS client" ))
1453+ }
1454+ container .attachmentStorage = repositories .NewGCSAttachmentStorage (
1455+ container .Logger (),
1456+ container .Tracer (),
1457+ client ,
1458+ bucket ,
1459+ )
1460+ } else {
1461+ container .logger .Debug ("creating MemoryAttachmentStorage (GCS_BUCKET_NAME not set)" )
1462+ container .attachmentStorage = repositories .NewMemoryAttachmentStorage (
1463+ container .Logger (),
1464+ container .Tracer (),
1465+ )
1466+ }
1467+
1468+ return container .attachmentStorage
1469+ }
1470+
1471+ // APIBaseURL returns the API base URL derived from EVENTS_QUEUE_ENDPOINT
1472+ func (container * Container ) APIBaseURL () string {
1473+ endpoint := os .Getenv ("EVENTS_QUEUE_ENDPOINT" )
1474+ return strings .TrimSuffix (endpoint , "/v1/events" )
1475+ }
1476+
1477+ // AttachmentHandler creates a new AttachmentHandler
1478+ func (container * Container ) AttachmentHandler () (handler * handlers.AttachmentHandler ) {
1479+ container .logger .Debug (fmt .Sprintf ("creating %T" , handler ))
1480+ return handlers .NewAttachmentHandler (
1481+ container .Logger (),
1482+ container .Tracer (),
1483+ container .AttachmentStorage (),
1484+ )
1485+ }
1486+
1487+ // RegisterAttachmentRoutes registers routes for the /attachments prefix
1488+ func (container * Container ) RegisterAttachmentRoutes () {
1489+ container .logger .Debug (fmt .Sprintf ("registering %T routes" , & handlers.AttachmentHandler {}))
1490+ container .AttachmentHandler ().RegisterRoutes (container .App ())
1491+ }
1492+
14361493// PhoneAPIKeyService creates a new instance of services.PhoneAPIKeyService
14371494func (container * Container ) PhoneAPIKeyService () (service * services.PhoneAPIKeyService ) {
14381495 container .logger .Debug (fmt .Sprintf ("creating %T" , service ))
0 commit comments