Skip to content

feat: add go-memory-load-mongo sample app#226

Open
pathakharshit wants to merge 1 commit into
mainfrom
feat/add-go-memory-load-mongo
Open

feat: add go-memory-load-mongo sample app#226
pathakharshit wants to merge 1 commit into
mainfrom
feat/add-go-memory-load-mongo

Conversation

@pathakharshit
Copy link
Copy Markdown

A sample Mongo app for k6 load test

Copilot AI review requested due to automatic review settings April 22, 2026 19:24
@pathakharshit pathakharshit requested review from Copilot and removed request for Copilot April 22, 2026 19:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new go-memory-load-mongo sample app that exposes a small HTTP API backed by MongoDB, plus a k6 scenario to generate mixed and large-payload load against it.

Changes:

  • Introduces a Mongo-backed store layer (customers/products/orders/analytics/large payloads) and HTTP handlers.
  • Adds Docker assets (Dockerfile + docker-compose) to run MongoDB, the API, and an optional k6 loadtest profile.
  • Adds k6 load scenario and Keploy config for recording/replay.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
go-memory-load-mongo/loadtest/scenario.js k6 load scenarios and thresholds for mixed API + large payload cycle
go-memory-load-mongo/keploy.yml Keploy configuration for record/replay
go-memory-load-mongo/internal/store/store.go MongoDB data access + validation + aggregation logic
go-memory-load-mongo/internal/store/models.go Request/response and persistence models
go-memory-load-mongo/internal/httpapi/server.go HTTP routing, handlers, JSON encoding/decoding, logging/recovery
go-memory-load-mongo/internal/database/mongo.go MongoDB connection and retrying ping logic
go-memory-load-mongo/internal/config/config.go Env-based config loading
go-memory-load-mongo/go.mod New Go module definition and dependencies
go-memory-load-mongo/go.sum Dependency lockfile entries
go-memory-load-mongo/docker-compose.yml Local runtime: MongoDB + API + k6 profile
go-memory-load-mongo/cmd/api/main.go API server entrypoint wiring config/db/store/http
go-memory-load-mongo/Dockerfile Container build for the API binary
go-memory-load-mongo/.env.example Example env vars for local runs
go-memory-load-mongo/.dockerignore Docker build context exclusions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

keployContainer: "keploy-v3"
keployNetwork: "keploy-network"

# Visit [https://keploy.io/docs/running-keploy/configuration-file/] to learn about using keploy through configration file.
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: “configration file” should be “configuration file”.

Suggested change
# Visit [https://keploy.io/docs/running-keploy/configuration-file/] to learn about using keploy through configration file.
# Visit [https://keploy.io/docs/running-keploy/configuration-file/] to learn about using keploy through configuration file.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
module loadtestmongoapi

go 1.26

require go.mongodb.org/mongo-driver/v2 v2.2.1

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new Go sample directory isn’t included in the golangci-lint workflow’s working-directory matrix, so CI linting won’t run for it. Add go-memory-load-mongo to .github/workflows/golangci-lint.yml to keep it consistent with the other Go samples.

Copilot uses AI. Check for mistakes.
Comment on lines +322 to +335
pipeline := mongo.Pipeline{
{{Key: "$match", Value: bson.M{"customer._id": customerID}}},
{{Key: "$unwind", Value: bson.M{"path": "$items", "preserveNullAndEmptyArrays": true}}},
{{Key: "$group", Value: bson.D{
{Key: "_id", Value: "$customer._id"},
{Key: "orders_count", Value: bson.M{"$addToSet": "$_id"}},
{Key: "lifetime_value_cents", Value: bson.M{"$sum": "$total_cents"}},
{Key: "last_order_at", Value: bson.M{"$max": "$created_at"}},
{Key: "category_spend", Value: bson.M{"$push": bson.M{
"category": "$items.category",
"cents": "$items.line_total_cents",
}}},
}}},
}
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The customer summary aggregation unwinds items before summing total_cents, which will overcount lifetime_value_cents (and affect average) by multiplying each order’s total_cents by its number of items. Consider grouping by order first (or using $first for total_cents) and then aggregating per customer so each order contributes once while still computing category spend.

Copilot uses AI. Check for mistakes.
// Either product not found or insufficient inventory.
var exists Product
if findErr := s.products.FindOne(ctx, bson.M{"_id": input.ProductID}).Decode(&exists); findErr != nil {
return Order{}, fmt.Errorf("%w: product %s", ErrNotFound, input.ProductID)
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When FindOneAndUpdate returns mongo.ErrNoDocuments, the follow-up FindOne treats any error as "not found". That will misclassify transient Mongo errors (timeouts, connection issues) as ErrNotFound. Handle mongo.ErrNoDocuments separately and return an internal error for other failures.

Suggested change
return Order{}, fmt.Errorf("%w: product %s", ErrNotFound, input.ProductID)
if errors.Is(findErr, mongo.ErrNoDocuments) {
return Order{}, fmt.Errorf("%w: product %s", ErrNotFound, input.ProductID)
}
return Order{}, fmt.Errorf("check product existence for %s: retry the request or verify database connectivity: %w", input.ProductID, findErr)

Copilot uses AI. Check for mistakes.
Items: items,
}

if _, err := s.orders.InsertOne(ctx, order); err != nil {
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InsertOne for orders does not handle duplicate key errors. Since order IDs are deterministic (contentID(customerID, fingerprint)), retries or repeated identical item sets can hit a duplicate and currently surface as a 500. Consider mapping mongo.IsDuplicateKeyError(err) to ErrConflict (similar to customers/products).

Suggested change
if _, err := s.orders.InsertOne(ctx, order); err != nil {
if _, err := s.orders.InsertOne(ctx, order); err != nil {
if mongo.IsDuplicateKeyError(err) {
return Order{}, fmt.Errorf("%w: order %s already exists", ErrConflict, order.ID)
}

Copilot uses AI. Check for mistakes.
skipCoverage: false
coverageReportPath: ""
ignoreOrdering: true
mongoPassword: "default@123"
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Keploy config file includes a hard-coded mongoPassword value. Even if it’s a default, committing passwords to the repo is risky and can be mistaken for a real credential. Prefer removing this field, using an environment variable reference, or replacing it with an obvious placeholder that can’t be used as-is.

Suggested change
mongoPassword: "default@123"
mongoPassword: "__SET_MONGO_PASSWORD__"

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants