Skip to content
Merged
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
14 changes: 2 additions & 12 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ DB_USER=
DB_PASSWORD=
DB_NAME=commercify

TEST_DB_HOST=localhost
TEST_DB_PORT=5432
TEST_DB_USER=postgres
TEST_DB_PASSWORD=postgres
TEST_DB_NAME=commercify_test

AUTH_JWT_SECRET=your_jwt_secret

EMAIL_ENABLED=true
Expand All @@ -27,11 +21,6 @@ STRIPE_PUBLIC_KEY=pk_test_your_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_signing_secret
STRIPE_PAYMENT_DESCRIPTION=Commercify Store Purchase

PAYPAL_ENABLED=true
PAYPAL_CLIENT_ID=your_client_id
PAYPAL_CLIENT_SECRET=your_client_secret
PAYPAL_SANDBOX=true

MOBILEPAY_ENABLED=false
MOBILEPAY_TEST_MODE=true
MOBILEPAY_MERCHANT_SERIAL_NUMBER=your_merchant_serial_number
Expand All @@ -42,4 +31,5 @@ MOBILEPAY_WEBHOOK_URL=https://your-site.com/api/webhooks/mobilepay
MOBILEPAY_PAYMENT_DESCRIPTION=Commercify Store Purchase
MOBILEPAY_MARKET=NOK

RETURN_URL=https://your-site.com/payment/complete
RETURN_URL=https://your-site.com/payment/complete
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
29 changes: 28 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help db-start db-stop db-restart db-logs db-clean migrate-up migrate-down seed-data build run test clean
.PHONY: help db-start db-stop db-restart db-logs db-clean migrate-up migrate-down seed-data build run test clean docker-build docker-build-tag docker-push docker-build-push

# Default target
help: ## Show this help message
Expand Down Expand Up @@ -41,6 +41,7 @@ build: ## Build the application
go build -o bin/api ./cmd/api
go build -o bin/migrate ./cmd/migrate
go build -o bin/seed ./cmd/seed
go build -o bin/expire-checkouts ./cmd/expire-checkouts

run: db-start ## Run the application locally with database
@echo "Starting database and waiting for it to be ready..."
Expand All @@ -56,6 +57,28 @@ stop-docker: ## Stop the entire application stack
logs: ## Show application logs
docker compose logs -f api

# Docker image commands
docker-build: ## Build Docker image
docker build -t ghcr.io/zenfulcode/commercifygo:latest .

docker-build-tag: ## Build Docker image with specific tag (use TAG=version)
@if [ -z "$(TAG)" ]; then echo "Error: TAG is required. Use: make docker-build-tag TAG=v1.0.0"; exit 1; fi
docker build -t ghcr.io/zenfulcode/commercifygo:$(TAG) -t ghcr.io/zenfulcode/commercifygo:latest -t ghcr.io/zenfulcode/commercifygo:dev .

docker-push: ## Push Docker image to registry (use REGISTRY and TAG)
@if [ -z "$(REGISTRY)" ]; then echo "Error: REGISTRY is required. Use: make docker-push REGISTRY=your-registry.com"; exit 1; fi
@if [ -z "$(TAG)" ]; then echo "Error: TAG is required. Use: make docker-push REGISTRY=your-registry.com TAG=v1.0.0"; exit 1; fi
# docker tag $(REGISTRY)commercifygo:$(TAG) $(REGISTRY)/commercifygo:$(TAG)
# docker tag $(REGISTRY)commercifygo:latest $(REGISTRY)/commercifygo:latest
docker push $(REGISTRY)/commercifygo:$(TAG)
docker push $(REGISTRY)/commercifygo:latest
docker push $(REGISTRY)/commercifygo:dev

docker-build-push: docker-build-tag docker-push ## Build and push Docker image (use REGISTRY and TAG)

docker-dev-build: ## Build Docker image for development
docker build -t ghcr.io/zenfulcode/commercifygo:dev .

# Development commands
test: ## Run tests
go test ./...
Expand Down Expand Up @@ -83,3 +106,7 @@ vet: ## Run go vet

mod-tidy: ## Tidy Go modules
go mod tidy

# Maintenance commands
expire-checkouts: ## Expire old checkouts manually
go run ./cmd/expire-checkouts
35 changes: 35 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func main() {
// Initialize API server
server := api.NewServer(cfg, db, logger)

// Start background checkout expiry process
go startCheckoutExpiryProcess(server, logger)

// Start server in a goroutine
go func() {
logger.Info("Starting server on port %s", cfg.Server.Port)
Expand All @@ -73,3 +76,35 @@ func main() {

logger.Info("Server exited properly")
}

// startCheckoutExpiryProcess runs a background process to expire old checkouts
func startCheckoutExpiryProcess(server *api.Server, logger logger.Logger) {
// Run every 15 minutes
ticker := time.NewTicker(15 * time.Minute)
defer ticker.Stop()

// Run immediately on startup
expireCheckouts(server, logger)

for range ticker.C {
expireCheckouts(server, logger)
}
}

// expireCheckouts expires old checkouts
func expireCheckouts(server *api.Server, logger logger.Logger) {
checkoutUseCase := server.GetContainer().UseCases().CheckoutUseCase()
if checkoutUseCase == nil {
logger.Error("CheckoutUseCase not available")
return
}

result, err := checkoutUseCase.ExpireOldCheckouts()
if err != nil {
logger.Error("Failed to expire old checkouts: %v", err)
} else {
logger.Info("Checkout cleanup completed: %d abandoned, %d deleted, %d expired (total: %d)",
result.AbandonedCount, result.DeletedCount, result.ExpiredCount,
result.AbandonedCount+result.DeletedCount+result.ExpiredCount)
}
}
53 changes: 53 additions & 0 deletions cmd/expire-checkouts/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"log"

"github.com/joho/godotenv"
"github.com/zenfulcode/commercify/config"
"github.com/zenfulcode/commercify/internal/infrastructure/container"
"github.com/zenfulcode/commercify/internal/infrastructure/database"
"github.com/zenfulcode/commercify/internal/infrastructure/logger"
)

func main() {
// Load environment variables
if err := godotenv.Load(); err != nil {
log.Println("No .env file found, using environment variables")
}

// Initialize logger
logger := logger.NewLogger()
logger.Info("Starting checkout expiry cleanup tool")

// Load configuration
cfg, err := config.LoadConfig()
if err != nil {
logger.Fatal("Failed to load configuration: %v", err)
}

// Connect to database
db, err := database.NewPostgresConnection(cfg.Database)
if err != nil {
logger.Fatal("Failed to connect to database: %v", err)
}
defer db.Close()

// Initialize dependency container
diContainer := container.NewContainer(cfg, db, logger)

// Get checkout use case
checkoutUseCase := diContainer.UseCases().CheckoutUseCase()

// Expire old checkouts
result, err := checkoutUseCase.ExpireOldCheckouts()
if err != nil {
logger.Fatal("Failed to expire old checkouts: %v", err)
}

logger.Info("Checkout cleanup completed:")
logger.Info("- Abandoned checkouts: %d", result.AbandonedCount)
logger.Info("- Deleted checkouts: %d", result.DeletedCount)
logger.Info("- Expired checkouts: %d", result.ExpiredCount)
logger.Info("Total processed: %d", result.AbandonedCount+result.DeletedCount+result.ExpiredCount)
}
Loading