Skip to content
Draft
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
22 changes: 20 additions & 2 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package app
import (
"fmt"
"net/http"
"time"

"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/transport"
Expand All @@ -21,6 +23,7 @@ import (
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/rs/zerolog"
"google.golang.org/grpc"
)
Expand All @@ -34,22 +37,35 @@ type App struct {
cleanup func()
}

// defaultPresignExpiry is used when PRESIGNED_URL_EXPIRY is not configured.
const defaultPresignExpiry = 15 * time.Minute

// New creates a new application with GraphQL handler and middleware.
func New(settings config.Settings) (*App, error) {
chConn, err := chClientFromSettings(&settings)
if err != nil {
return nil, fmt.Errorf("failed to create ClickHouse connection: %w", err)
}
s3Client := s3ClientFromSettings(&settings)
presignClient := s3.NewPresignClient(s3Client)
buckets := []string{settings.CloudEventBucket, settings.EphemeralBucket}
eventService := eventrepo.New(chConn, s3Client, settings.ParquetBucket)

presignExpiry := defaultPresignExpiry
if settings.PresignedURLExpiry != "" {
d, err := time.ParseDuration(settings.PresignedURLExpiry)
if err != nil {
return nil, fmt.Errorf("invalid PRESIGNED_URL_EXPIRY %q: %w", settings.PresignedURLExpiry, err)
}
presignExpiry = d
}

var identityClient identity.Client
if settings.IdentityAPIURL != "" {
identityClient = identity.New(settings.IdentityAPIURL)
}

gqlSrv := newGraphQLHandler(&settings, eventService, buckets, identityClient)
gqlSrv := newGraphQLHandler(&settings, eventService, buckets, identityClient, presignClient, presignExpiry)

jwtMiddleware, err := auth.NewJWTMiddleware(settings.TokenExchangeIssuer, settings.TokenExchangeJWTKeySetURL)
if err != nil {
Expand Down Expand Up @@ -91,11 +107,13 @@ func (a *App) Cleanup() {
}

// newGraphQLHandler creates a configured gqlgen handler.Server.
func newGraphQLHandler(settings *config.Settings, eventService *eventrepo.Service, buckets []string, identityClient identity.Client) *handler.Server {
func newGraphQLHandler(settings *config.Settings, eventService *eventrepo.Service, buckets []string, identityClient identity.Client, presignClient *s3.PresignClient, presignExpiry time.Duration) *handler.Server {
resolver := &graph.Resolver{
EventService: eventService,
Buckets: buckets,
IdentityClient: identityClient,
Presigner: presignClient,
PresignExpiry: presignExpiry,
}

cfg := graph.Config{Resolvers: resolver}
Expand Down
1 change: 1 addition & 0 deletions internal/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Settings struct {
CloudEventBucket string `yaml:"CLOUDEVENT_BUCKET"`
EphemeralBucket string `yaml:"EPHEMERAL_BUCKET"`
ParquetBucket string `yaml:"PARQUET_BUCKET"`
PresignedURLExpiry string `yaml:"PRESIGNED_URL_EXPIRY"` // e.g. "15m"; defaults to 15m if empty
S3AWSRegion string `yaml:"S3_AWS_REGION"`
S3AWSAccessKeyID string `yaml:"S3_AWS_ACCESS_KEY_ID"`
S3AWSSecretAccessKey string `yaml:"S3_AWS_SECRET_ACCESS_KEY"`
Expand Down
55 changes: 49 additions & 6 deletions internal/graph/base.resolvers.go

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

4 changes: 3 additions & 1 deletion internal/graph/cloud_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (

// CloudEventWrapper holds a pointer to a RawEvent so resolvers can expose
// header, data, and dataBase64 without copying the underlying event.
// For large single-file events, PresignedURL is set and Data/DataBase64 are null.
type CloudEventWrapper struct {
Raw *cloudevent.RawEvent
Raw *cloudevent.RawEvent
PresignedURL string // non-empty for large single-event refs; clients should fetch from this URL
}

// RawJSON is the raw bytes of a JSON value. It implements graphql.Marshaler by
Expand Down
84 changes: 80 additions & 4 deletions internal/graph/generated.go

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

Loading
Loading