From 8ef126bb3ab84f4da18b833360f16268ef131089 Mon Sep 17 00:00:00 2001 From: sergeyb Date: Sat, 21 Feb 2026 02:19:36 +0000 Subject: [PATCH] refactor(all): The Grand Rename --- .envrc | 2 +- CLAUDE.md | 42 ++--- Makefile | 50 ++--- README.md | 54 +++--- {docs => doc}/architecture/STRUCTURE.md | 8 +- {docs/designs => doc/design}/README.md | 0 {docs/designs => doc/design}/sql-queue-rfc.md | 8 +- {integration_tests => e2e_test}/BUILD.bazel | 14 +- {integration_tests => e2e_test}/README.md | 53 ++++-- .../queue/BUILD.bazel | 10 +- .../queue/queue_test.go | 178 +++++++++--------- {integration_tests => e2e_test}/servers.go | 8 +- {integration_tests => e2e_test}/suite_test.go | 8 +- .../testutil/BUILD.bazel | 2 +- .../testutil/docker.go | 0 .../testutil/mysql.go | 4 +- {entities => entity}/BUILD.bazel | 4 +- {entities => entity}/queue/BUILD.bazel | 2 +- {entities => entity}/queue/message.go | 0 {entities => entity}/queue/message_test.go | 0 {entities => entity}/request.go | 2 +- {examples => example}/README.md | 56 +++--- .../client/gateway/BUILD.bazel | 2 +- {examples => example}/client/gateway/main.go | 0 .../client/orchestrator/BUILD.bazel | 2 +- .../client/orchestrator/main.go | 0 .../client/speculator/BUILD.bazel | 2 +- .../client/speculator/main.go | 0 .../server/gateway/BUILD.bazel | 6 +- {examples => example}/server/gateway/main.go | 14 +- .../server/orchestrator/BUILD.bazel | 2 +- .../server/orchestrator/main.go | 0 .../server/speculator/BUILD.bazel | 2 +- .../server/speculator/main.go | 0 {extensions => extension}/counter/BUILD.bazel | 2 +- {extensions => extension}/counter/README.md | 4 +- {extensions => extension}/counter/counter.go | 0 .../counter/mysql/BUILD.bazel | 4 +- .../counter/mysql/counter.go | 2 +- .../counter/mysql/schema/BUILD.bazel | 0 .../counter/mysql/schema/counter.sql | 0 {extensions => extension}/queue/BUILD.bazel | 4 +- {extensions => extension}/queue/README.md | 2 +- {extensions => extension}/queue/delivery.go | 2 +- {extensions => extension}/queue/publisher.go | 2 +- {extensions => extension}/queue/queue.go | 0 .../queue/sql/BUILD.bazel | 10 +- {extensions => extension}/queue/sql/README.md | 4 +- {extensions => extension}/queue/sql/config.go | 0 .../queue/sql/config_test.go | 0 .../queue/sql/constants.go | 0 {extensions => extension}/queue/sql/errors.go | 0 .../queue/sql/message_store.go | 2 +- .../queue/sql/message_store_test.go | 2 +- .../queue/sql/mock_stores.go | 2 +- .../queue/sql/offset_store.go | 0 .../queue/sql/offset_store_test.go | 0 .../queue/sql/partition_lease_store.go | 0 .../queue/sql/partition_lease_store_test.go | 0 .../queue/sql/publisher.go | 2 +- .../queue/sql/publisher_test.go | 4 +- .../queue/sql/schema/BUILD.bazel | 0 .../queue/sql/schema/queue_messages.sql | 0 .../queue/sql/schema/queue_offsets.sql | 0 .../sql/schema/queue_partition_leases.sql | 0 {extensions => extension}/queue/sql/sql.go | 10 +- .../queue/sql/sql_test.go | 102 +++++----- {extensions => extension}/queue/sql/stores.go | 2 +- .../queue/sql/subscriber.go | 4 +- .../queue/sql/subscriber_test.go | 2 +- .../queue/sql/validation.go | 0 {extensions => extension}/queue/subscriber.go | 0 {extensions => extension}/storage/BUILD.bazel | 4 +- .../storage/mysql/BUILD.bazel | 8 +- .../storage/mysql/request_store.go | 18 +- .../storage/mysql/schema/BUILD.bazel | 0 .../storage/mysql/schema/request.sql | 0 .../storage/mysql/storage.go | 16 +- .../storage/request_store.go | 8 +- {extensions => extension}/storage/storage.go | 9 +- gateway/controller/BUILD.bazel | 10 +- gateway/controller/land.go | 32 ++-- gateway/controller/land_test.go | 62 +++--- .../BUILD.bazel | 2 +- .../ping_test.go | 0 .../BUILD.bazel | 2 +- .../ping_test.go | 0 .../BUILD.bazel | 2 +- .../ping_test.go | 0 {tools => tool}/BUILD.bazel | 0 {tools => tool}/README.md | 14 +- {tools => tool}/bazel | 6 +- 92 files changed, 461 insertions(+), 435 deletions(-) rename {docs => doc}/architecture/STRUCTURE.md (94%) rename {docs/designs => doc/design}/README.md (100%) rename {docs/designs => doc/design}/sql-queue-rfc.md (98%) rename {integration_tests => e2e_test}/BUILD.bazel (75%) rename {integration_tests => e2e_test}/README.md (53%) rename {integration_tests => e2e_test}/queue/BUILD.bazel (79%) rename {integration_tests => e2e_test}/queue/queue_test.go (91%) rename {integration_tests => e2e_test}/servers.go (94%) rename {integration_tests => e2e_test}/suite_test.go (96%) rename {integration_tests => e2e_test}/testutil/BUILD.bazel (87%) rename {integration_tests => e2e_test}/testutil/docker.go (100%) rename {integration_tests => e2e_test}/testutil/mysql.go (96%) rename {entities => entity}/BUILD.bazel (61%) rename {entities => entity}/queue/BUILD.bazel (82%) rename {entities => entity}/queue/message.go (100%) rename {entities => entity}/queue/message_test.go (100%) rename {entities => entity}/request.go (99%) rename {examples => example}/README.md (78%) rename {examples => example}/client/gateway/BUILD.bazel (85%) rename {examples => example}/client/gateway/main.go (100%) rename {examples => example}/client/orchestrator/BUILD.bazel (85%) rename {examples => example}/client/orchestrator/main.go (100%) rename {examples => example}/client/speculator/BUILD.bazel (85%) rename {examples => example}/client/speculator/main.go (100%) rename {examples => example}/server/gateway/BUILD.bazel (79%) rename {examples => example}/server/gateway/main.go (91%) rename {examples => example}/server/orchestrator/BUILD.bazel (87%) rename {examples => example}/server/orchestrator/main.go (100%) rename {examples => example}/server/speculator/BUILD.bazel (87%) rename {examples => example}/server/speculator/main.go (100%) rename {extensions => extension}/counter/BUILD.bazel (69%) rename {extensions => extension}/counter/README.md (86%) rename {extensions => extension}/counter/counter.go (100%) rename {extensions => extension}/counter/mysql/BUILD.bazel (61%) rename {extensions => extension}/counter/mysql/counter.go (94%) rename {extensions => extension}/counter/mysql/schema/BUILD.bazel (100%) rename {extensions => extension}/counter/mysql/schema/counter.sql (100%) rename {extensions => extension}/queue/BUILD.bazel (70%) rename {extensions => extension}/queue/README.md (96%) rename {extensions => extension}/queue/delivery.go (97%) rename {extensions => extension}/queue/publisher.go (88%) rename {extensions => extension}/queue/queue.go (100%) rename {extensions => extension}/queue/sql/BUILD.bazel (86%) rename {extensions => extension}/queue/sql/README.md (95%) rename {extensions => extension}/queue/sql/config.go (100%) rename {extensions => extension}/queue/sql/config_test.go (100%) rename {extensions => extension}/queue/sql/constants.go (100%) rename {extensions => extension}/queue/sql/errors.go (100%) rename {extensions => extension}/queue/sql/message_store.go (99%) rename {extensions => extension}/queue/sql/message_store_test.go (99%) rename {extensions => extension}/queue/sql/mock_stores.go (99%) rename {extensions => extension}/queue/sql/offset_store.go (100%) rename {extensions => extension}/queue/sql/offset_store_test.go (100%) rename {extensions => extension}/queue/sql/partition_lease_store.go (100%) rename {extensions => extension}/queue/sql/partition_lease_store_test.go (100%) rename {extensions => extension}/queue/sql/publisher.go (97%) rename {extensions => extension}/queue/sql/publisher_test.go (98%) rename {extensions => extension}/queue/sql/schema/BUILD.bazel (100%) rename {extensions => extension}/queue/sql/schema/queue_messages.sql (100%) rename {extensions => extension}/queue/sql/schema/queue_offsets.sql (100%) rename {extensions => extension}/queue/sql/schema/queue_partition_leases.sql (100%) rename {extensions => extension}/queue/sql/sql.go (90%) rename {extensions => extension}/queue/sql/sql_test.go (77%) rename {extensions => extension}/queue/sql/stores.go (99%) rename {extensions => extension}/queue/sql/subscriber.go (99%) rename {extensions => extension}/queue/sql/subscriber_test.go (98%) rename {extensions => extension}/queue/sql/validation.go (100%) rename {extensions => extension}/queue/subscriber.go (100%) rename {extensions => extension}/storage/BUILD.bazel (67%) rename {extensions => extension}/storage/mysql/BUILD.bazel (61%) rename {extensions => extension}/storage/mysql/request_store.go (85%) rename {extensions => extension}/storage/mysql/schema/BUILD.bazel (100%) rename {extensions => extension}/storage/mysql/schema/request.sql (100%) rename extensions/storage/mysql/factory.go => extension/storage/mysql/storage.go (81%) rename {extensions => extension}/storage/request_store.go (78%) rename {extensions => extension}/storage/storage.go (74%) rename gateway/{integration_tests => integration_test}/BUILD.bazel (91%) rename gateway/{integration_tests => integration_test}/ping_test.go (100%) rename orchestrator/{integration_tests => integration_test}/BUILD.bazel (91%) rename orchestrator/{integration_tests => integration_test}/ping_test.go (100%) rename speculator/{integration_tests => integration_test}/BUILD.bazel (91%) rename speculator/{integration_tests => integration_test}/ping_test.go (100%) rename {tools => tool}/BUILD.bazel (100%) rename {tools => tool}/README.md (70%) rename {tools => tool}/bazel (98%) diff --git a/.envrc b/.envrc index b5c58f97..6275d343 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,4 @@ -PATH_add tools +PATH_add tool REPO_ROOT=$(pwd) export REPO_ROOT diff --git a/CLAUDE.md b/CLAUDE.md index 9ecc0f08..998a042b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,19 +49,19 @@ Three services, each following the same layout: ├── controller/ # Business logic (pure, transport-agnostic) ├── proto/ # Proto definitions (.proto files) ├── protopb/ # Generated proto code (committed to repo) -└── integration_tests/ +└── integration_test/ ``` ### Controllers -Controllers contain pure business logic, independent of the transport layer (gRPC/YARPC). They live in `{service}/controller/` and are wired up in `examples/server/{service}/main.go`. +Controllers contain pure business logic, independent of the transport layer (gRPC/YARPC). They live in `{service}/controller/` and are wired up in `example/server/{service}/main.go`. ### Entities -Domain objects in `entities/`, organized by domain. Top-level entities live directly in `entities/`; domain-specific ones go in subdirectories. +Domain objects in `entity/`, organized by domain. Top-level entities live directly in `entity/`; domain-specific ones go in subdirectories. ``` -entities/ +entity/ ├── request.go # Request, Change, enums (RequestState, RequestLandStrategy) └── queue/ └── message.go # Message entity @@ -80,7 +80,7 @@ entities/ Extensions are **vendor-agnostic, pluggable interfaces** for backend implementations. Each defines interfaces at the top level with implementations in subdirectories. ``` -extensions/ +extension/ ├── counter/ # Atomic sequential number generation │ ├── counter.go # Counter interface │ └── mysql/ # MySQL implementation @@ -91,14 +91,14 @@ extensions/ │ ├── delivery.go # Delivery interface │ └── sql/ # SQL (MySQL) implementation └── storage/ # Storage abstraction - ├── storage.go # StoreFactory interface + sentinel errors + ├── storage.go # Storage (factory) interface + sentinel errors ├── request_store.go # RequestStore interface └── mysql/ # MySQL implementation ``` **Extension pattern:** -1. Define vendor-agnostic interfaces at `extensions/{extension}/` -2. Implementations go in `extensions/{extension}/{impl}/` +1. Define vendor-agnostic interfaces at `extension/{ext}/` +2. Implementations go in `extension/{ext}/{impl}/` 3. Most extensions use a Factory interface for dependency injection and lifecycle management 4. Include a README.md documenting interfaces and usage @@ -106,9 +106,9 @@ extensions/ - Controllers: `github.com/uber/submitqueue/{service}/controller` - Proto (generated): `github.com/uber/submitqueue/{service}/protopb` -- Extensions: `github.com/uber/submitqueue/extensions/{extension}` -- Extension impl: `github.com/uber/submitqueue/extensions/{extension}/{impl}` -- Entities: `github.com/uber/submitqueue/entities/{domain}` +- Extensions: `github.com/uber/submitqueue/extension/{extension}` +- Extension impl: `github.com/uber/submitqueue/extension/{extension}/{impl}` +- Entities: `github.com/uber/submitqueue/entity/{domain}` ## Development @@ -122,17 +122,17 @@ submitqueue/ ├── Makefile # Build automation ├── .bazelversion # Pinned Bazel version ├── .envrc # direnv configuration -├── tools/bazel # Bazelisk wrapper +├── tool/bazel # Bazelisk wrapper ├── gateway/ # Gateway service ├── orchestrator/ # Orchestrator service ├── speculator/ # Speculator service -├── extensions/ # Pluggable backend implementations -├── entities/ # Domain entities -├── examples/ # Server and client examples +├── extension/ # Pluggable backend implementations +├── entity/ # Domain entities +├── example/ # Server and client examples │ ├── server/{service}/ │ └── client/{service}/ -├── integration_tests/ # Cross-service hermetic tests (Testcontainers) -├── docs/ # Documentation +├── e2e_test/ # Cross-service hermetic tests (Testcontainers) +├── doc/ # Documentation └── bin/ # Compiled binaries (gitignored) ``` @@ -143,7 +143,7 @@ This repository uses **Bazel with Bzlmod** (NOT WORKSPACE) for dependency manage - **Version pinning**: `.bazelversion` pins the Bazel version - **Dependencies**: Managed in `MODULE.bazel` (NOT a WORKSPACE file) - **Go version**: Defined in `go.mod`, read by `MODULE.bazel` via `go_sdk.from_file()` -- **Bazel wrapper**: `./tools/bazel` (Bazelisk wrapper). With direnv (`.envrc`), use `bazel` directly. +- **Bazel wrapper**: `./tool/bazel` (Bazelisk wrapper). With direnv (`.envrc`), use `bazel` directly. - **External dependencies**: Must be added to both `go.mod` AND `MODULE.bazel` - **BUILD files**: Every Go package must have a `BUILD.bazel` file @@ -187,16 +187,16 @@ make clean-proto # Remove generated proto files 1. Edit `{service}/proto/*.proto` 2. `make proto` 3. Add controller in `{service}/controller/` -4. Wire up in `examples/server/{service}/main.go` +4. Wire up in `example/server/{service}/main.go` **Add new extension implementation:** -1. Create `extensions/{extension}/{impl}/` directory +1. Create `extension/{extension}/{impl}/` directory 2. Implement factory and core interfaces 3. Add `BUILD.bazel` 4. Add tests and document in README.md **Add new entity:** -1. Create `entities/{domain}/{entity}.go` with test file +1. Create `entity/{domain}/{entity}.go` with test file 2. Add `BUILD.bazel` with `go_library` and `go_test` targets ### Testing Guidelines diff --git a/Makefile b/Makefile index 3239e6bb..cc537a70 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: proto build test integration-test integration-test-gateway integration-test-orchestrator integration-test-speculator e2e-test gazelle clean run-all start-servers stop-servers run-gateway run-orchestrator run-speculator run-client-gateway run-client-orchestrator run-client-speculator # Bazel wrapper -BAZEL = ./tools/bazel +BAZEL = ./tool/bazel # Generate protobuf files for all services using protoc proto: @@ -26,18 +26,18 @@ build: @$(BAZEL) build //... @echo "Copying binaries to ./bin/..." @mkdir -p bin - @cp -f bazel-bin/examples/server/gateway/gateway_/gateway bin/gateway_server 2>/dev/null || \ - cp -f bazel-bin/examples/server/gateway/gateway bin/gateway_server 2>/dev/null || true - @cp -f bazel-bin/examples/server/orchestrator/orchestrator_/orchestrator bin/orchestrator_server 2>/dev/null || \ - cp -f bazel-bin/examples/server/orchestrator/orchestrator bin/orchestrator_server 2>/dev/null || true - @cp -f bazel-bin/examples/server/speculator/speculator_/speculator bin/speculator_server 2>/dev/null || \ - cp -f bazel-bin/examples/server/speculator/speculator bin/speculator_server 2>/dev/null || true - @cp -f bazel-bin/examples/client/gateway/gateway_/gateway bin/gateway_client 2>/dev/null || \ - cp -f bazel-bin/examples/client/gateway/gateway bin/gateway_client 2>/dev/null || true - @cp -f bazel-bin/examples/client/orchestrator/orchestrator_/orchestrator bin/orchestrator_client 2>/dev/null || \ - cp -f bazel-bin/examples/client/orchestrator/orchestrator bin/orchestrator_client 2>/dev/null || true - @cp -f bazel-bin/examples/client/speculator/speculator_/speculator bin/speculator_client 2>/dev/null || \ - cp -f bazel-bin/examples/client/speculator/speculator bin/speculator_client 2>/dev/null || true + @cp -f bazel-bin/example/server/gateway/gateway_/gateway bin/gateway_server 2>/dev/null || \ + cp -f bazel-bin/example/server/gateway/gateway bin/gateway_server 2>/dev/null || true + @cp -f bazel-bin/example/server/orchestrator/orchestrator_/orchestrator bin/orchestrator_server 2>/dev/null || \ + cp -f bazel-bin/example/server/orchestrator/orchestrator bin/orchestrator_server 2>/dev/null || true + @cp -f bazel-bin/example/server/speculator/speculator_/speculator bin/speculator_server 2>/dev/null || \ + cp -f bazel-bin/example/server/speculator/speculator bin/speculator_server 2>/dev/null || true + @cp -f bazel-bin/example/client/gateway/gateway_/gateway bin/gateway_client 2>/dev/null || \ + cp -f bazel-bin/example/client/gateway/gateway bin/gateway_client 2>/dev/null || true + @cp -f bazel-bin/example/client/orchestrator/orchestrator_/orchestrator bin/orchestrator_client 2>/dev/null || \ + cp -f bazel-bin/example/client/orchestrator/orchestrator bin/orchestrator_client 2>/dev/null || true + @cp -f bazel-bin/example/client/speculator/speculator_/speculator bin/speculator_client 2>/dev/null || \ + cp -f bazel-bin/example/client/speculator/speculator bin/speculator_client 2>/dev/null || true @echo "Build complete! Binaries are in ./bin/" # Run unit tests using Bazel (excludes integration tests which require running servers) @@ -53,25 +53,25 @@ gazelle: # Run integration tests for a specific service (requires that service to be running) integration-test-gateway: @echo "Running Gateway integration tests..." - @$(BAZEL) test //gateway/integration_tests:integration_tests_test --test_output=all + @$(BAZEL) test //gateway/integration_test:integration_test_test --test_output=all integration-test-orchestrator: @echo "Running Orchestrator integration tests..." - @$(BAZEL) test //orchestrator/integration_tests:integration_tests_test --test_output=all + @$(BAZEL) test //orchestrator/integration_test:integration_test_test --test_output=all integration-test-speculator: @echo "Running Speculator integration tests..." - @$(BAZEL) test //speculator/integration_tests:integration_tests_test --test_output=all + @$(BAZEL) test //speculator/integration_test:integration_test_test --test_output=all # Run all service integration tests (requires all services to be running) integration-test: @echo "Running all service integration tests..." - @$(BAZEL) test //gateway/integration_tests:integration_tests_test //orchestrator/integration_tests:integration_tests_test //speculator/integration_tests:integration_tests_test --test_output=all + @$(BAZEL) test //gateway/integration_test:integration_test_test //orchestrator/integration_test:integration_test_test //speculator/integration_test:integration_test_test --test_output=all # Run end-to-end integration tests (hermetic, no manual server setup needed) e2e-test: @echo "Running integration tests..." - @$(BAZEL) test //integration_tests:integration_test --test_output=all + @$(BAZEL) test //e2e_test:e2e_test --test_output=all # Clean generated files and binaries clean: @@ -124,29 +124,29 @@ run-all: start-servers # Run gateway server using Bazel run-gateway: @echo "Starting gateway server on port 8081..." - @$(BAZEL) run //examples/server/gateway:gateway + @$(BAZEL) run //example/server/gateway:gateway # Run orchestrator server using Bazel run-orchestrator: @echo "Starting orchestrator server on port 8082..." - @$(BAZEL) run //examples/server/orchestrator:orchestrator + @$(BAZEL) run //example/server/orchestrator:orchestrator # Run speculator server using Bazel run-speculator: @echo "Starting speculator server on port 8083..." - @$(BAZEL) run //examples/server/speculator:speculator + @$(BAZEL) run //example/server/speculator:speculator # Run gateway client using Bazel run-client-gateway: - @$(BAZEL) run //examples/client/gateway:gateway -- -addr $(or $(SERVER_ADDR),localhost:8081) -message "$(or $(MESSAGE),ping)" + @$(BAZEL) run //example/client/gateway:gateway -- -addr $(or $(SERVER_ADDR),localhost:8081) -message "$(or $(MESSAGE),ping)" # Run orchestrator client using Bazel run-client-orchestrator: - @$(BAZEL) run //examples/client/orchestrator:orchestrator -- -addr $(or $(SERVER_ADDR),localhost:8082) -message "$(or $(MESSAGE),ping)" + @$(BAZEL) run //example/client/orchestrator:orchestrator -- -addr $(or $(SERVER_ADDR),localhost:8082) -message "$(or $(MESSAGE),ping)" # Run speculator client using Bazel run-client-speculator: - @$(BAZEL) run //examples/client/speculator:speculator -- -addr $(or $(SERVER_ADDR),localhost:8083) -message "$(or $(MESSAGE),ping)" + @$(BAZEL) run //example/client/speculator:speculator -- -addr $(or $(SERVER_ADDR),localhost:8083) -message "$(or $(MESSAGE),ping)" # Install dependencies (for go mod users) deps: @@ -160,7 +160,7 @@ query-targets: @$(BAZEL) query //... query-deps: - @$(BAZEL) query 'deps(//examples/server/gateway:gateway)' + @$(BAZEL) query 'deps(//example/server/gateway:gateway)' # Help help: diff --git a/README.md b/README.md index f26d00c1..85cd4380 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,13 @@ Build and run a service: make run-gateway # Using Go directly -go run examples/server/gateway/main.go +go run example/server/gateway/main.go # Using Bazel (with direnv) -bazel run //examples/server/gateway:gateway +bazel run //example/server/gateway:gateway # Or without direnv -./tools/bazel run //examples/server/gateway:gateway +./tool/bazel run //example/server/gateway:gateway ``` Test the service: @@ -38,17 +38,17 @@ Test the service: make run-client-gateway MESSAGE="hello" # Or using Go directly -go run examples/client/gateway/main.go -message "hello" +go run example/client/gateway/main.go -message "hello" # Or using grpcurl grpcurl -plaintext -d '{"message": "hello"}' localhost:8081 uber.devexp.submitqueue.gateway.SubmitQueueGateway/Ping ``` -For detailed instructions, see [examples/README.md](examples/README.md). +For detailed instructions, see [example/README.md](example/README.md). ## Project Structure -See [docs/architecture/STRUCTURE.md](docs/architecture/STRUCTURE.md) for a detailed breakdown of the project structure. +See [doc/architecture/STRUCTURE.md](doc/architecture/STRUCTURE.md) for a detailed breakdown of the project structure. ## Architecture @@ -58,7 +58,7 @@ The project follows clean architecture principles with clear separation of conce - Only depend on logger, metrics, and protobuf types - Example: `PingController` handles ping business logic -- **Server Adapters** (`examples/server/`): gRPC transport layer +- **Server Adapters** (`example/server/`): gRPC transport layer - Wrap controllers and implement gRPC service interfaces - Handle protocol-specific concerns (e.g., `UnimplementedServiceServer`) @@ -76,7 +76,7 @@ The project follows clean architecture principles with clear separation of conce - **grpcurl** (optional, for manual testing) - **direnv** (recommended, to automatically load `.envrc`) -**Note**: The project includes `./tools/bazel` (bazelisk wrapper) and `.bazelversion`, so you don't need to install Bazel or Bazelisk separately. +**Note**: The project includes `./tool/bazel` (bazelisk wrapper) and `.bazelversion`, so you don't need to install Bazel or Bazelisk separately. #### Using direnv (Recommended) @@ -92,7 +92,7 @@ eval "$(direnv hook zsh)" # or bash, fish, etc. direnv allow ``` -With direnv enabled, you can use `bazel` directly instead of `./tools/bazel`. +With direnv enabled, you can use `bazel` directly instead of `./tool/bazel`. Install optional tools: ```bash @@ -145,14 +145,14 @@ make proto go build ./... # Build example servers -go build -o bin/gateway_server ./examples/server/gateway/ -go build -o bin/orchestrator_server ./examples/server/orchestrator/ -go build -o bin/speculator_server ./examples/server/speculator/ +go build -o bin/gateway_server ./example/server/gateway/ +go build -o bin/orchestrator_server ./example/server/orchestrator/ +go build -o bin/speculator_server ./example/server/speculator/ # Build clients -go build -o bin/gateway_client ./examples/client/gateway/ -go build -o bin/orchestrator_client ./examples/client/orchestrator/ -go build -o bin/speculator_client ./examples/client/speculator/ +go build -o bin/gateway_client ./example/client/gateway/ +go build -o bin/orchestrator_client ./example/client/orchestrator/ +go build -o bin/speculator_client ./example/client/speculator/ # Run a server ./bin/gateway_server @@ -165,25 +165,25 @@ go build -o bin/speculator_client ./examples/client/speculator/ The project uses **Bzlmod** (not WORKSPACE) for dependency management. Bazel version is pinned at 8.4.1 in `.bazelversion`. -The project includes `./tools/bazel` which automatically downloads the correct Bazel version. If you're using `direnv`, you can simply use `bazel` instead of `./tools/bazel`. +The project includes `./tool/bazel` which automatically downloads the correct Bazel version. If you're using `direnv`, you can simply use `bazel` instead of `./tool/bazel`. ```bash # Build everything (with direnv) bazel build //... # Or without direnv -./tools/bazel build //... +./tool/bazel build //... # Build specific components bazel build //gateway/protopb -bazel build //examples/server/gateway:gateway -bazel build //examples/client/gateway:gateway +bazel build //example/server/gateway:gateway +bazel build //example/client/gateway:gateway # Run a server -bazel run //examples/server/gateway:gateway +bazel run //example/server/gateway:gateway # Run a client -bazel run //examples/client/gateway:gateway -- -message "hello" +bazel run //example/client/gateway:gateway -- -message "hello" # Or use the Makefile (recommended) make build @@ -193,11 +193,11 @@ make run-gateway **Note**: - The repository uses Bzlmod for modern dependency management - All generated proto files are committed to the repository -- With `direnv` enabled, use `bazel` directly; otherwise use `./tools/bazel` +- With `direnv` enabled, use `bazel` directly; otherwise use `./tool/bazel` ### Running Services -See the [examples directory](examples/) for examples of running each service. +See the [examples directory](example/) for examples of running each service. ## Development Workflow @@ -226,7 +226,7 @@ When you make changes to `.proto` files, you need to regenerate the protobuf cod 4. Update client examples to display new fields: ```bash - # Edit examples/client/gateway/main.go to show the new field + # Edit example/client/gateway/main.go to show the new field ``` 5. Rebuild and test: @@ -358,7 +358,7 @@ make test 4. **Create server wrapper in example:** ```go - // In examples/server/gateway/main.go + // In example/server/gateway/main.go // Add method delegation to GatewayServer struct: func (s *GatewayServer) NewMethod(ctx context.Context, req *pb.NewRequest) (*pb.NewResponse, error) { return s.newController.NewMethod(ctx, req) @@ -403,6 +403,6 @@ bazel clean **Bazel build issues:** - Bazel version is pinned to 8.4.1 in `.bazelversion` -- With `direnv`, you can use `bazel` directly; otherwise use `./tools/bazel` -- Try `bazel shutdown` (or `./tools/bazel shutdown`) and rebuild +- With `direnv`, you can use `bazel` directly; otherwise use `./tool/bazel` +- Try `bazel shutdown` (or `./tool/bazel shutdown`) and rebuild - The wrapper automatically downloads the correct Bazel version diff --git a/docs/architecture/STRUCTURE.md b/doc/architecture/STRUCTURE.md similarity index 94% rename from docs/architecture/STRUCTURE.md rename to doc/architecture/STRUCTURE.md index afea36f3..f71ba358 100644 --- a/docs/architecture/STRUCTURE.md +++ b/doc/architecture/STRUCTURE.md @@ -13,7 +13,7 @@ submitqueue/ ├── Makefile # Build automation ├── BUILD.bazel # Root build file │ -├── tools/ # Bazel tooling +├── tool/ # Bazel tooling │ ├── bazel # Python-based Bazelisk wrapper │ ├── BUILD.bazel │ └── README.md @@ -63,7 +63,7 @@ submitqueue/ │ ├── speculator_grpc.pb.go │ └── speculator.pb.yarpc.go │ -└── examples/ # Examples (like tango/example) +└── example/ # Examples (like tango/example) ├── README.md ├── server/ # Server examples │ ├── gateway/ @@ -99,7 +99,7 @@ This allows services to support both gRPC and YARPC clients. ### 3. **Python-Based Bazel Wrapper** -The `tools/bazel` script is a Python implementation of Bazelisk that: +The `tool/bazel` script is a Python implementation of Bazelisk that: - Reads `.bazelversion` to determine which Bazel version to use - Downloads and caches the appropriate Bazel binary - Delegates to the correct version automatically @@ -121,5 +121,5 @@ All `*pb/` generated files are committed to the repository because: | Dependency mgmt | Bzlmod | Bzlmod | | YARPC | Yes | Yes | | Generated committed | Yes | Yes | -| Examples dir | `example/` | `examples/server/` and `examples/client/` | +| Examples dir | `example/` | `example/server/` and `example/client/` | | Bazel config | No `.bazelrc` | No `.bazelrc` | diff --git a/docs/designs/README.md b/doc/design/README.md similarity index 100% rename from docs/designs/README.md rename to doc/design/README.md diff --git a/docs/designs/sql-queue-rfc.md b/doc/design/sql-queue-rfc.md similarity index 98% rename from docs/designs/sql-queue-rfc.md rename to doc/design/sql-queue-rfc.md index ddab675f..0e166a3f 100644 --- a/docs/designs/sql-queue-rfc.md +++ b/doc/design/sql-queue-rfc.md @@ -159,7 +159,7 @@ We chose **custom database-backed queue** because: - `(topic, partition_key, invisible_until, offset)`: Core fetch query - find visible messages in partition ordered by offset - `(topic, partition_key, id)`: Unique constraint and fast lookup for Ack/Nack -See `extensions/queue/sql/schema/queue_messages.sql` for full schema. +See `extension/queue/sql/schema/queue_messages.sql` for full schema. ### Partition Leases Table @@ -172,7 +172,7 @@ See `extensions/queue/sql/schema/queue_messages.sql` for full schema. - `(leased_by)`: Find all partitions owned by a worker - `(lease_renewed_at)`: Detect stale leases across workers -See `extensions/queue/sql/schema/queue_partition_leases.sql` for full schema. +See `extension/queue/sql/schema/queue_partition_leases.sql` for full schema. ### Consumer Offsets Table @@ -185,7 +185,7 @@ See `extensions/queue/sql/schema/queue_partition_leases.sql` for full schema. - `(consumer_group)`: Monitor all offsets for a consumer group - `(topic)`: Find all consumers for a topic -See `extensions/queue/sql/schema/queue_offsets.sql` for full schema. +See `extension/queue/sql/schema/queue_offsets.sql` for full schema. ### Dead Letter Queue Table @@ -201,7 +201,7 @@ See `extensions/queue/sql/schema/queue_offsets.sql` for full schema. - `(failed_at)`: Time-based queries and cleanup - `(topic, partition_key, id)`: Unique constraint, prevents duplicates -See `extensions/queue/sql/schema/queue_dlq.sql` for full schema. +See `extension/queue/sql/schema/queue_dlq.sql` for full schema. ## Message Flow diff --git a/integration_tests/BUILD.bazel b/e2e_test/BUILD.bazel similarity index 75% rename from integration_tests/BUILD.bazel rename to e2e_test/BUILD.bazel index 12ef2e5b..aa7b2ad0 100644 --- a/integration_tests/BUILD.bazel +++ b/e2e_test/BUILD.bazel @@ -3,21 +3,21 @@ load("@rules_go//go:def.bzl", "go_test") go_test( - name = "integration_test", + name = "e2e_test", srcs = [ "servers.go", "suite_test.go", ], data = [ - "//extensions/counter/mysql/schema", - "//extensions/storage/mysql/schema", - "//examples/server/gateway", - "//examples/server/orchestrator", - "//examples/server/speculator", + "//extension/counter/mysql/schema", + "//extension/storage/mysql/schema", + "//example/server/gateway", + "//example/server/orchestrator", + "//example/server/speculator", ], tags = ["integration"], deps = [ - "//integration_tests/testutil", + "//e2e_test/testutil", "//gateway/protopb", "//orchestrator/protopb", "//speculator/protopb", diff --git a/integration_tests/README.md b/e2e_test/README.md similarity index 53% rename from integration_tests/README.md rename to e2e_test/README.md index d2fe8a8e..327f4922 100644 --- a/integration_tests/README.md +++ b/e2e_test/README.md @@ -1,6 +1,6 @@ -# Integration Tests +# End-to-End (E2E) Tests -This directory contains hermetic integration tests for the SubmitQueue system. All infrastructure (MySQL, gRPC servers) is managed automatically via [Testcontainers-Go](https://golang.testcontainers.org/) — no manual setup required. +This directory contains hermetic end-to-end tests for the SubmitQueue system. All infrastructure (MySQL, gRPC servers) is managed automatically via [Testcontainers-Go](https://golang.testcontainers.org/) — no manual setup required. ## Architecture @@ -8,44 +8,71 @@ Tests run as a `testify/suite` that manages the full lifecycle: 1. **Docker network** is created for inter-container communication 2. **MySQL container** starts on the network (alias `mysql`), schema is applied -3. **Server containers** (gateway, orchestrator, speculator) are built from the actual `go_binary` targets in `examples/server/` and started on the network +3. **Server containers** (gateway, orchestrator, speculator) are built from the actual `go_binary` targets in `example/server/` and started on the network 4. **gRPC clients** connect to the mapped host ports 5. **Tests execute** against the real server binaries 6. **Cleanup** tears down all containers and the network All servers listen on port `8080` inside their containers. Docker maps each to a random host port, so there are no port conflicts even when tests run in parallel. The fixed internal port also simplifies inter-service communication on the Docker network — services reach each other at `:8080` (e.g., `orchestrator:8080`). -## Files +## Structure -| File | Purpose | +| Path | Purpose | |------|---------| | `suite_test.go` | Test suite with `SetupSuite`/`TearDownSuite` and all test methods | | `servers.go` | Helpers to build Docker images from server binaries and start containers | -| `mysql.go` | MySQL container setup, schema application, and test logger | -| `BUILD.bazel` | Bazel test target with binary and schema data dependencies | +| `testutil/docker.go` | Docker environment setup (network creation, Ryuk/HOME workarounds) | +| `testutil/mysql.go` | MySQL container setup, schema application, and test logger | +| `queue/queue_test.go` | SQL queue integration tests (publish, subscribe, partitioning, DLQ) | ## Running Tests ```bash -# Run with Bazel -bazel test //integration_tests:integration_test --test_output=all +# Run all e2e tests with Bazel +bazel test //e2e_test/... --test_output=all + +# Run only the service-level suite +bazel test //e2e_test:e2e_test --test_output=all + +# Run only the queue tests +bazel test //e2e_test/queue:queue_test --test_output=all # Run with verbose output -bazel test //integration_tests:integration_test --test_output=all --test_arg=-test.v +bazel test //e2e_test/... --test_output=all --test_arg=-test.v # Run with Go (from repo root) -go test ./integration_tests -v +go test ./e2e_test/... -v ``` -The test target is tagged `integration` (not `manual`), so it is discovered by `bazel test //integration_tests/...`. +The test targets are tagged `integration` (not `manual`), so they are discovered by `bazel test //e2e_test/...`. ## Test Cases +### Service suite (`suite_test.go`) + - `TestPingGateway` — Ping gateway, assert `service_name="gateway"` - `TestPingOrchestrator` — Ping orchestrator, assert `service_name="orchestrator"` - `TestPingSpeculator` — Ping speculator, assert `service_name="speculator"` - `TestLandRequest` — Send `LandRequest` through gateway gRPC, assert `sqid` is returned +### Queue suite (`queue/queue_test.go`) + +- `TestPublishAndSubscribe` — Basic publish/subscribe round-trip +- `TestMultiplePartitions` — Messages distribute across partitions +- `TestVisibilityTimeoutAndRetry` — Un-acked messages become visible again +- `TestNackWithDelay` — Nack redelivers with configurable delay +- `TestIdempotentPublish` — Duplicate message IDs are deduplicated +- `TestConcurrentPublishers` — Multiple publishers write safely +- `TestCrashRecovery` — Subscriber resumes from last committed offset +- `TestMultipleConsumerGroups` — Independent consumer groups each get all messages +- `TestMultipleWorkersInConsumerGroup` — Workers share partitions within a group +- `TestConcurrentSubscribers` — Concurrent subscribers process without duplication +- `TestDeadLetterQueue` — Failed messages move to DLQ after max retries +- `TestMessageOrderingWithinPartition` — Order preserved within a partition +- `TestLateSubscriber` — New subscriber reads existing messages +- `TestEmptyTopicSubscribe` — Subscribing to an empty topic blocks gracefully +- `TestGracefulShutdownDuringProcessing` — Close mid-processing without data loss + ## Adding New Tests Add a method to `IntegrationSuite` in `suite_test.go`: @@ -75,7 +102,7 @@ _, addr := startServerContainer(ctx, t, log, "gateway", map[string]string{ **Ryuk reaper failure** — The Testcontainers reaper container may fail in Docker-in-Docker environments. This is handled by setting `TESTCONTAINERS_RYUK_DISABLED=true` in `SetupSuite`. -**Binary not found** — Ensure the `data` attribute in `BUILD.bazel` includes the server binary targets. Bazel places them in runfiles at `examples/server//_/`. +**Binary not found** — Ensure the `data` attribute in `BUILD.bazel` includes the server binary targets. Bazel places them in runfiles at `example/server//_/`. ## TODO diff --git a/integration_tests/queue/BUILD.bazel b/e2e_test/queue/BUILD.bazel similarity index 79% rename from integration_tests/queue/BUILD.bazel rename to e2e_test/queue/BUILD.bazel index af3da33f..dd373428 100644 --- a/integration_tests/queue/BUILD.bazel +++ b/e2e_test/queue/BUILD.bazel @@ -4,14 +4,14 @@ go_test( name = "queue_test", srcs = ["queue_test.go"], data = [ - "//extensions/queue/sql/schema", + "//extension/queue/sql/schema", ], tags = ["integration"], deps = [ - "//entities/queue", - "//extensions/queue", - "//extensions/queue/sql", - "//integration_tests/testutil", + "//entity/queue", + "//extension/queue", + "//extension/queue/sql", + "//e2e_test/testutil", "@com_github_go_sql_driver_mysql//:mysql", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/integration_tests/queue/queue_test.go b/e2e_test/queue/queue_test.go similarity index 91% rename from integration_tests/queue/queue_test.go rename to e2e_test/queue/queue_test.go index 0c2db7f4..410b5b5f 100644 --- a/integration_tests/queue/queue_test.go +++ b/e2e_test/queue/queue_test.go @@ -18,10 +18,10 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap/zaptest" - "github.com/uber/submitqueue/entities/queue" - extqueue "github.com/uber/submitqueue/extensions/queue" - queueSQL "github.com/uber/submitqueue/extensions/queue/sql" - "github.com/uber/submitqueue/integration_tests/testutil" + "github.com/uber/submitqueue/entity/queue" + extqueue "github.com/uber/submitqueue/extension/queue" + queueSQL "github.com/uber/submitqueue/extension/queue/sql" + "github.com/uber/submitqueue/e2e_test/testutil" ) type QueueIntegrationSuite struct { @@ -47,7 +47,7 @@ func (s *QueueIntegrationSuite) SetupSuite() { s.network, s.ctx = testutil.SetupDockerEnv(t, s.log, s.ctx) // Setup MySQL using shared helper - s.container, s.db, s.dsn = testutil.SetupMySQL(t, s.log, s.network, "extensions/queue/sql/schema") + s.container, s.db, s.dsn = testutil.SetupMySQL(t, s.log, s.network, "extension/queue/sql/schema") } func (s *QueueIntegrationSuite) TearDownSuite() { @@ -96,19 +96,19 @@ func receiveNWithTimeout( func (s *QueueIntegrationSuite) TestPublishAndSubscribe() { t := s.T() - // Create queue factory + // Create queue config := queueSQL.DefaultConfig("test-consumer", "test-worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "test_topic" @@ -169,17 +169,17 @@ func (s *QueueIntegrationSuite) TestMultiplePartitions() { t := s.T() config := queueSQL.DefaultConfig("multi-partition-consumer", "worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "multi_partition_topic" @@ -219,17 +219,17 @@ func (s *QueueIntegrationSuite) TestVisibilityTimeoutAndRetry() { config.VisibilityTimeout = 2 * time.Second config.PollInterval = 100 * time.Millisecond - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "retry_topic" @@ -305,17 +305,17 @@ func (s *QueueIntegrationSuite) TestNackWithDelay() { config := queueSQL.DefaultConfig("nack-consumer", "worker-1") config.PollInterval = 100 * time.Millisecond - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "nack_topic" @@ -357,17 +357,17 @@ func (s *QueueIntegrationSuite) TestIdempotentPublish() { t := s.T() config := queueSQL.DefaultConfig("idempotent-consumer", "worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "idempotent_topic" @@ -405,17 +405,17 @@ func (s *QueueIntegrationSuite) TestConcurrentPublishers() { t := s.T() config := queueSQL.DefaultConfig("concurrent-consumer", "worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() topic := "concurrent_topic" @@ -468,7 +468,7 @@ func (s *QueueIntegrationSuite) TestCrashRecovery() { config.LeaseDuration = 3 * time.Second // Short lease for testing crash recovery config.LeaseRenewalInterval = 1 * time.Second // Must be less than LeaseDuration - factory1, err := queueSQL.NewQueue(queueSQL.Params{ + q1, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, @@ -476,8 +476,8 @@ func (s *QueueIntegrationSuite) TestCrashRecovery() { }) require.NoError(t, err) - publisher := factory1.Publisher() - subscriber1 := factory1.Subscriber() + publisher := q1.Publisher() + subscriber1 := q1.Subscriber() topic := "crash_topic" @@ -494,9 +494,9 @@ func (s *QueueIntegrationSuite) TestCrashRecovery() { t.Logf("Worker 1 received message but crashing without ack") assert.Equal(t, "crash-msg", delivery1.Message().ID) - // Simulate crash by closing factory1 - factory1.Close() - t.Logf("Worker 1 crashed (factory closed)") + // Simulate crash by closing q1 + q1.Close() + t.Logf("Worker 1 crashed (queue closed)") // Wait for both visibility timeout AND partition lease to expire waitTime := config.LeaseDuration + config.VisibilityTimeout + time.Second @@ -510,16 +510,16 @@ func (s *QueueIntegrationSuite) TestCrashRecovery() { config2.LeaseDuration = 3 * time.Second config2.LeaseRenewalInterval = 1 * time.Second - factory2, err := queueSQL.NewQueue(queueSQL.Params{ + q2, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config2, }) require.NoError(t, err) - defer factory2.Close() + defer q2.Close() - subscriber2 := factory2.Subscriber() + subscriber2 := q2.Subscriber() deliveryChan2, err := subscriber2.Subscribe(s.ctx, topic) require.NoError(t, err) @@ -541,28 +541,28 @@ func (s *QueueIntegrationSuite) TestMultipleConsumerGroups() { // Create two different consumer groups config1 := queueSQL.DefaultConfig("group-A", "worker-1") - factory1, err := queueSQL.NewQueue(queueSQL.Params{ + q1, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config1, }) require.NoError(t, err) - defer factory1.Close() + defer q1.Close() config2 := queueSQL.DefaultConfig("group-B", "worker-1") - factory2, err := queueSQL.NewQueue(queueSQL.Params{ + q2, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config2, }) require.NoError(t, err) - defer factory2.Close() + defer q2.Close() - publisher := factory1.Publisher() - subscriber1 := factory1.Subscriber() - subscriber2 := factory2.Subscriber() + publisher := q1.Publisher() + subscriber1 := q1.Subscriber() + subscriber2 := q2.Subscriber() // Subscribe both groups deliveryChan1, err := subscriber1.Subscribe(s.ctx, topic) @@ -622,28 +622,28 @@ func (s *QueueIntegrationSuite) TestMultipleWorkersInConsumerGroup() { // Create two workers in same consumer group config1 := queueSQL.DefaultConfig(consumerGroup, "worker-1") - factory1, err := queueSQL.NewQueue(queueSQL.Params{ + q1, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config1, }) require.NoError(t, err) - defer factory1.Close() + defer q1.Close() config2 := queueSQL.DefaultConfig(consumerGroup, "worker-2") - factory2, err := queueSQL.NewQueue(queueSQL.Params{ + q2, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config2, }) require.NoError(t, err) - defer factory2.Close() + defer q2.Close() - publisher := factory1.Publisher() - subscriber1 := factory1.Subscriber() - subscriber2 := factory2.Subscriber() + publisher := q1.Publisher() + subscriber1 := q1.Subscriber() + subscriber2 := q2.Subscriber() // Subscribe both workers deliveryChan1, err := subscriber1.Subscribe(s.ctx, topic) @@ -741,42 +741,42 @@ func (s *QueueIntegrationSuite) TestConcurrentSubscribers() { // Create publisher publisherConfig := queueSQL.DefaultConfig(consumerGroup, "publisher") - publisherFactory, err := queueSQL.NewQueue(queueSQL.Params{ + pubQueue, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: publisherConfig, }) require.NoError(t, err) - defer publisherFactory.Close() + defer pubQueue.Close() - publisher := publisherFactory.Publisher() + publisher := pubQueue.Publisher() // Create multiple concurrent subscribers - var factories []extqueue.Queue + var queues []extqueue.Queue var deliveryChans []<-chan extqueue.Delivery for i := 0; i < numSubscribers; i++ { config := queueSQL.DefaultConfig(consumerGroup, fmt.Sprintf("worker-%d", i)) - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - factories = append(factories, factory) + queues = append(queues, q) - subscriber := factory.Subscriber() + subscriber := q.Subscriber() deliveryChan, err := subscriber.Subscribe(s.ctx, topic) require.NoError(t, err) deliveryChans = append(deliveryChans, deliveryChan) } - // Cleanup all factories + // Cleanup all queues defer func() { - for _, f := range factories { - f.Close() + for _, q := range queues { + q.Close() } }() @@ -855,17 +855,17 @@ func (s *QueueIntegrationSuite) TestDeadLetterQueue() { config.Retry.MaxAttempts = 2 // Only 2 attempts before DLQ config.DLQ.Enabled = true - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() // Subscribe to main topic deliveryChan, err := subscriber.Subscribe(s.ctx, topic) @@ -945,17 +945,17 @@ func (s *QueueIntegrationSuite) TestMessageOrderingWithinPartition() { partitionKey := "ordered-partition" config := queueSQL.DefaultConfig("ordering-consumer", "worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() // Subscribe first deliveryChan, err := subscriber.Subscribe(s.ctx, topic) @@ -997,16 +997,16 @@ func (s *QueueIntegrationSuite) TestLateSubscriber() { topic := "late_subscriber_topic" config := queueSQL.DefaultConfig("late-consumer", "worker-1") - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - publisher := factory.Publisher() + publisher := q.Publisher() // Publish messages BEFORE subscribing numMessages := 5 @@ -1020,7 +1020,7 @@ func (s *QueueIntegrationSuite) TestLateSubscriber() { t.Logf("Published %d messages BEFORE subscribing", numMessages) // Now subscribe (late subscriber) - subscriber := factory.Subscriber() + subscriber := q.Subscriber() deliveryChan, err := subscriber.Subscribe(s.ctx, topic) require.NoError(t, err) t.Logf("Late subscriber joined after messages published") @@ -1050,16 +1050,16 @@ func (s *QueueIntegrationSuite) TestEmptyTopicSubscribe() { config := queueSQL.DefaultConfig("empty-consumer", "worker-1") config.PollInterval = 100 * time.Millisecond - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() - subscriber := factory.Subscriber() + subscriber := q.Subscriber() // Subscribe to empty topic (no messages published yet) deliveryChan, err := subscriber.Subscribe(s.ctx, topic) @@ -1075,7 +1075,7 @@ func (s *QueueIntegrationSuite) TestEmptyTopicSubscribe() { } // Now publish a message - publisher := factory.Publisher() + publisher := q.Publisher() msg := queue.NewMessage("late-msg", []byte("data"), "partition-1", nil) require.NoError(t, publisher.Publish(s.ctx, topic, msg)) t.Logf("Published message to previously-empty topic") @@ -1095,7 +1095,7 @@ func (s *QueueIntegrationSuite) TestGracefulShutdownDuringProcessing() { config := queueSQL.DefaultConfig("shutdown-consumer", "worker-1") config.PollInterval = 100 * time.Millisecond - factory, err := queueSQL.NewQueue(queueSQL.Params{ + q, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, @@ -1103,8 +1103,8 @@ func (s *QueueIntegrationSuite) TestGracefulShutdownDuringProcessing() { }) require.NoError(t, err) - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() // Subscribe deliveryChan, err := subscriber.Subscribe(s.ctx, topic) @@ -1123,11 +1123,11 @@ func (s *QueueIntegrationSuite) TestGracefulShutdownDuringProcessing() { inFlightMsgID := delivery.Message().ID t.Logf("Received in-flight message: %s (not acked yet)", inFlightMsgID) - // Close the factory while message is in-flight - t.Logf("Closing factory with in-flight message...") - err = factory.Close() + // Close the queue while message is in-flight + t.Logf("Closing queue with in-flight message...") + err = q.Close() require.NoError(t, err) - t.Logf("Factory closed successfully") + t.Logf("Queue closed successfully") // Drain any buffered messages from the channel without acking them // These messages were already fetched and marked invisible @@ -1160,16 +1160,16 @@ drainLoop: // Start new subscriber to verify all messages are redelivered t.Logf("Starting new subscriber to verify message recovery...") - factory2, err := queueSQL.NewQueue(queueSQL.Params{ + q2, err := queueSQL.NewQueue(queueSQL.Params{ DB: s.db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NoopScope, Config: config, }) require.NoError(t, err) - defer factory2.Close() + defer q2.Close() - subscriber2 := factory2.Subscriber() + subscriber2 := q2.Subscriber() deliveryChan2, err := subscriber2.Subscribe(s.ctx, topic) require.NoError(t, err) diff --git a/integration_tests/servers.go b/e2e_test/servers.go similarity index 94% rename from integration_tests/servers.go rename to e2e_test/servers.go index 0708c81a..d7fb87c2 100644 --- a/integration_tests/servers.go +++ b/e2e_test/servers.go @@ -1,4 +1,4 @@ -package integration_tests +package e2etest import ( "context" @@ -12,7 +12,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/network" "github.com/testcontainers/testcontainers-go/wait" - "github.com/uber/submitqueue/integration_tests/testutil" + "github.com/uber/submitqueue/e2e_test/testutil" ) const serverPort = "8080" @@ -21,9 +21,9 @@ const serverPort = "8080" func serverBinaryPath(name string) string { if dir := os.Getenv("TEST_SRCDIR"); dir != "" { workspace := os.Getenv("TEST_WORKSPACE") - return filepath.Join(dir, workspace, "examples/server", name, name+"_", name) + return filepath.Join(dir, workspace, "example/server", name, name+"_", name) } - return filepath.Join("examples/server", name, name) + return filepath.Join("example/server", name, name) } // startServerContainer builds a Docker image from the server binary and starts it. diff --git a/integration_tests/suite_test.go b/e2e_test/suite_test.go similarity index 96% rename from integration_tests/suite_test.go rename to e2e_test/suite_test.go index d3e370ad..0ea54b33 100644 --- a/integration_tests/suite_test.go +++ b/e2e_test/suite_test.go @@ -1,4 +1,4 @@ -package integration_tests +package e2etest import ( "context" @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/testcontainers/testcontainers-go" gatewaypb "github.com/uber/submitqueue/gateway/protopb" - "github.com/uber/submitqueue/integration_tests/testutil" + "github.com/uber/submitqueue/e2e_test/testutil" orchestratorpb "github.com/uber/submitqueue/orchestrator/protopb" speculatorpb "github.com/uber/submitqueue/speculator/protopb" "google.golang.org/grpc" @@ -42,8 +42,8 @@ func (s *IntegrationSuite) SetupSuite() { s.nw, ctx = testutil.SetupDockerEnv(t, s.log, ctx) // Start MySQL container on the network and apply schemas. - mysqlContainer, db, _ := testutil.SetupMySQL(t, s.log, s.nw, "extensions/storage/mysql/schema") - testutil.ApplySchema(t, s.log, db, testutil.SchemaDir("extensions/counter/mysql/schema")) + mysqlContainer, db, _ := testutil.SetupMySQL(t, s.log, s.nw, "extension/storage/mysql/schema") + testutil.ApplySchema(t, s.log, db, testutil.SchemaDir("extension/counter/mysql/schema")) // Register MySQL cleanup s.addCleanup(func() { diff --git a/integration_tests/testutil/BUILD.bazel b/e2e_test/testutil/BUILD.bazel similarity index 87% rename from integration_tests/testutil/BUILD.bazel rename to e2e_test/testutil/BUILD.bazel index 3d909e9f..d6112052 100644 --- a/integration_tests/testutil/BUILD.bazel +++ b/e2e_test/testutil/BUILD.bazel @@ -6,7 +6,7 @@ go_library( "docker.go", "mysql.go", ], - importpath = "github.com/uber/submitqueue/integration_tests/testutil", + importpath = "github.com/uber/submitqueue/e2e_test/testutil", visibility = ["//visibility:public"], deps = [ "@com_github_go_sql_driver_mysql//:mysql", diff --git a/integration_tests/testutil/docker.go b/e2e_test/testutil/docker.go similarity index 100% rename from integration_tests/testutil/docker.go rename to e2e_test/testutil/docker.go diff --git a/integration_tests/testutil/mysql.go b/e2e_test/testutil/mysql.go similarity index 96% rename from integration_tests/testutil/mysql.go rename to e2e_test/testutil/mysql.go index 51c70d6b..5c51e29d 100644 --- a/integration_tests/testutil/mysql.go +++ b/e2e_test/testutil/mysql.go @@ -42,7 +42,7 @@ func (l *TestLogger) Logf(format string, args ...any) { // SchemaDir returns the path to a schema directory. // It checks for both Bazel runfiles and direct go test paths. -// relativePath should be like "extensions/storage/mysql/schema" or "extensions/queue/sql/schema" +// relativePath should be like "extension/storage/mysql/schema" or "extension/queue/sql/schema" func SchemaDir(relativePath string) string { // Bazel runfiles path if dir := os.Getenv("TEST_SRCDIR"); dir != "" { @@ -80,7 +80,7 @@ func ApplySchema(t *testing.T, log *TestLogger, db *sql.DB, schemaDirectory stri // SetupMySQL starts a MySQL container on the given Docker network, applies the schema, // and returns the container, db connection, and DSN for use in tests. // The caller is responsible for cleanup (closing db, terminating container). -// schemaPath is the relative path to the schema directory (e.g., "extensions/storage/mysql/schema"). +// schemaPath is the relative path to the schema directory (e.g., "extension/storage/mysql/schema"). func SetupMySQL(t *testing.T, log *TestLogger, nw *testcontainers.DockerNetwork, schemaPath string) (*mysql.MySQLContainer, *sql.DB, string) { t.Helper() diff --git a/entities/BUILD.bazel b/entity/BUILD.bazel similarity index 61% rename from entities/BUILD.bazel rename to entity/BUILD.bazel index 627f0fa5..b9002664 100644 --- a/entities/BUILD.bazel +++ b/entity/BUILD.bazel @@ -1,8 +1,8 @@ load("@rules_go//go:def.bzl", "go_library") go_library( - name = "entities", + name = "entity", srcs = ["request.go"], - importpath = "github.com/uber/submitqueue/entities", + importpath = "github.com/uber/submitqueue/entity", visibility = ["//visibility:public"], ) diff --git a/entities/queue/BUILD.bazel b/entity/queue/BUILD.bazel similarity index 82% rename from entities/queue/BUILD.bazel rename to entity/queue/BUILD.bazel index e9f1afbc..07192954 100644 --- a/entities/queue/BUILD.bazel +++ b/entity/queue/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "queue", srcs = ["message.go"], - importpath = "github.com/uber/submitqueue/entities/queue", + importpath = "github.com/uber/submitqueue/entity/queue", visibility = ["//visibility:public"], ) diff --git a/entities/queue/message.go b/entity/queue/message.go similarity index 100% rename from entities/queue/message.go rename to entity/queue/message.go diff --git a/entities/queue/message_test.go b/entity/queue/message_test.go similarity index 100% rename from entities/queue/message_test.go rename to entity/queue/message_test.go diff --git a/entities/request.go b/entity/request.go similarity index 99% rename from entities/request.go rename to entity/request.go index 02c1cf71..b0c7fe3c 100644 --- a/entities/request.go +++ b/entity/request.go @@ -1,4 +1,4 @@ -package entities +package entity // RequestLandStrategy defines the possible source control integration methods. diff --git a/examples/README.md b/example/README.md similarity index 78% rename from examples/README.md rename to example/README.md index 91359c24..9c7bf896 100644 --- a/examples/README.md +++ b/example/README.md @@ -39,52 +39,52 @@ make clean Build a specific server: ```bash # Build gateway server -bazel build //examples/server/gateway:gateway +bazel build //example/server/gateway:gateway # Build orchestrator server -bazel build //examples/server/orchestrator:orchestrator +bazel build //example/server/orchestrator:orchestrator # Build speculator server -bazel build //examples/server/speculator:speculator +bazel build //example/server/speculator:speculator # Build clients -bazel build //examples/client/gateway:gateway -bazel build //examples/client/orchestrator:orchestrator -bazel build //examples/client/speculator:speculator +bazel build //example/client/gateway:gateway +bazel build //example/client/orchestrator:orchestrator +bazel build //example/client/speculator:speculator ``` Run a specific server: ```bash # Run gateway server -bazel run //examples/server/gateway:gateway +bazel run //example/server/gateway:gateway # Run orchestrator server -bazel run //examples/server/orchestrator:orchestrator +bazel run //example/server/orchestrator:orchestrator # Run speculator server -bazel run //examples/server/speculator:speculator +bazel run //example/server/speculator:speculator # Or use '.' from the directory -cd examples/server/gateway && bazel run . -cd examples/server/orchestrator && bazel run . -cd examples/server/speculator && bazel run . +cd example/server/gateway && bazel run . +cd example/server/orchestrator && bazel run . +cd example/server/speculator && bazel run . ``` Run clients: ```bash # Run gateway client -bazel run //examples/client/gateway:gateway -- -message "hello" +bazel run //example/client/gateway:gateway -- -message "hello" # Run orchestrator client -bazel run //examples/client/orchestrator:orchestrator -- -message "hello" +bazel run //example/client/orchestrator:orchestrator -- -message "hello" # Run speculator client -bazel run //examples/client/speculator:speculator -- -message "hello" +bazel run //example/client/speculator:speculator -- -message "hello" # Or use '.' from the directory -cd examples/client/gateway && bazel run . -- -message "hello" -cd examples/client/orchestrator && bazel run . -- -message "hello" -cd examples/client/speculator && bazel run . -- -message "hello" +cd example/client/gateway && bazel run . -- -message "hello" +cd example/client/orchestrator && bazel run . -- -message "hello" +cd example/client/speculator && bazel run . -- -message "hello" ``` ### Using Go directly @@ -93,18 +93,18 @@ You can also run the servers directly with Go (from the repository root): ```bash # Run gateway server -go run examples/server/gateway/main.go +go run example/server/gateway/main.go # Run orchestrator server -go run examples/server/orchestrator/main.go +go run example/server/orchestrator/main.go # Run speculator server -go run examples/server/speculator/main.go +go run example/server/speculator/main.go # Run clients -go run examples/client/gateway/main.go -message "hello" -go run examples/client/orchestrator/main.go -message "hello" -go run examples/client/speculator/main.go -message "hello" +go run example/client/gateway/main.go -message "hello" +go run example/client/orchestrator/main.go -message "hello" +go run example/client/speculator/main.go -message "hello" ``` ## Testing the Services @@ -119,9 +119,9 @@ make run-client-orchestrator MESSAGE="test from orchestrator client" make run-client-speculator MESSAGE="test from speculator client" # Using Go -go run examples/client/gateway/main.go -addr localhost:8081 -message "hello" -go run examples/client/orchestrator/main.go -addr localhost:8082 -message "hello" -go run examples/client/speculator/main.go -addr localhost:8083 -message "hello" +go run example/client/gateway/main.go -addr localhost:8081 -message "hello" +go run example/client/orchestrator/main.go -addr localhost:8082 -message "hello" +go run example/client/speculator/main.go -addr localhost:8083 -message "hello" ``` Client flags: @@ -228,7 +228,7 @@ Each service directory (in the repository root) contains: - `ping.go`: Ping service implementation - `BUILD.bazel`: Bazel build rules -The `examples/` directory contains: +The `example/` directory contains: - `server/`: Example server implementations - `gateway/`, `orchestrator/`, `speculator/`: Server examples - `client/`: Example client implementations diff --git a/examples/client/gateway/BUILD.bazel b/example/client/gateway/BUILD.bazel similarity index 85% rename from examples/client/gateway/BUILD.bazel rename to example/client/gateway/BUILD.bazel index a1d3a890..9e5305e7 100644 --- a/examples/client/gateway/BUILD.bazel +++ b/example/client/gateway/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "gateway_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/client/gateway", + importpath = "github.com/uber/submitqueue/example/client/gateway", visibility = ["//visibility:private"], deps = [ "//gateway/protopb", diff --git a/examples/client/gateway/main.go b/example/client/gateway/main.go similarity index 100% rename from examples/client/gateway/main.go rename to example/client/gateway/main.go diff --git a/examples/client/orchestrator/BUILD.bazel b/example/client/orchestrator/BUILD.bazel similarity index 85% rename from examples/client/orchestrator/BUILD.bazel rename to example/client/orchestrator/BUILD.bazel index ca3b99c9..086177b6 100644 --- a/examples/client/orchestrator/BUILD.bazel +++ b/example/client/orchestrator/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "orchestrator_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/client/orchestrator", + importpath = "github.com/uber/submitqueue/example/client/orchestrator", visibility = ["//visibility:private"], deps = [ "//orchestrator/protopb", diff --git a/examples/client/orchestrator/main.go b/example/client/orchestrator/main.go similarity index 100% rename from examples/client/orchestrator/main.go rename to example/client/orchestrator/main.go diff --git a/examples/client/speculator/BUILD.bazel b/example/client/speculator/BUILD.bazel similarity index 85% rename from examples/client/speculator/BUILD.bazel rename to example/client/speculator/BUILD.bazel index fdff4a65..fd253303 100644 --- a/examples/client/speculator/BUILD.bazel +++ b/example/client/speculator/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "speculator_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/client/speculator", + importpath = "github.com/uber/submitqueue/example/client/speculator", visibility = ["//visibility:private"], deps = [ "//speculator/protopb", diff --git a/examples/client/speculator/main.go b/example/client/speculator/main.go similarity index 100% rename from examples/client/speculator/main.go rename to example/client/speculator/main.go diff --git a/examples/server/gateway/BUILD.bazel b/example/server/gateway/BUILD.bazel similarity index 79% rename from examples/server/gateway/BUILD.bazel rename to example/server/gateway/BUILD.bazel index 1708aae1..94d2768a 100644 --- a/examples/server/gateway/BUILD.bazel +++ b/example/server/gateway/BUILD.bazel @@ -3,11 +3,11 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "gateway_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/server/gateway", + importpath = "github.com/uber/submitqueue/example/server/gateway", visibility = ["//visibility:private"], deps = [ - "//extensions/counter/mysql", - "//extensions/storage/mysql", + "//extension/counter/mysql", + "//extension/storage/mysql", "//gateway/controller", "//gateway/protopb", "@com_github_go_sql_driver_mysql//:mysql", diff --git a/examples/server/gateway/main.go b/example/server/gateway/main.go similarity index 91% rename from examples/server/gateway/main.go rename to example/server/gateway/main.go index fa6fe0b4..fa2d87af 100644 --- a/examples/server/gateway/main.go +++ b/example/server/gateway/main.go @@ -13,8 +13,8 @@ import ( _ "github.com/go-sql-driver/mysql" "github.com/uber-go/tally/v4" - mysqlcounter "github.com/uber/submitqueue/extensions/counter/mysql" - "github.com/uber/submitqueue/extensions/storage/mysql" + mysqlcounter "github.com/uber/submitqueue/extension/counter/mysql" + "github.com/uber/submitqueue/extension/storage/mysql" "github.com/uber/submitqueue/gateway/controller" pb "github.com/uber/submitqueue/gateway/protopb" "go.uber.org/zap" @@ -85,21 +85,21 @@ func run() error { metricsWgDone.Wait() }() - // Initialize MySQL storage factory + // Initialize MySQL storage mysqlDSN := os.Getenv("MYSQL_DSN") if mysqlDSN == "" { mysqlDSN = "root:root@tcp(localhost:3306)/submitqueue?parseTime=true" } - storeFactory, err := mysql.NewFactory(mysql.MySQLParameters{ + store, err := mysql.NewStorage(mysql.MySQLParameters{ DSN: mysqlDSN, MaxOpenConns: 10, MaxIdleConns: 5, ConnMaxLifetime: 5 * time.Minute, }) if err != nil { - return fmt.Errorf("failed to create MySQL storage factory: %w", err) + return fmt.Errorf("failed to create MySQL storage: %w", err) } - defer storeFactory.Close() + defer store.Close() // Initialize MySQL counter counterDB, err := sql.Open("mysql", mysqlDSN) @@ -114,7 +114,7 @@ func run() error { // Create controllers and wrap them for gRPC pingController := controller.NewPingController(logger, scope) - landController := controller.NewLandController(logger, scope, storeFactory, cnt) + landController := controller.NewLandController(logger, scope, store, cnt) gatewayServer := &GatewayServer{ pingController: pingController, landController: landController, diff --git a/examples/server/orchestrator/BUILD.bazel b/example/server/orchestrator/BUILD.bazel similarity index 87% rename from examples/server/orchestrator/BUILD.bazel rename to example/server/orchestrator/BUILD.bazel index f80d09fa..95f833e8 100644 --- a/examples/server/orchestrator/BUILD.bazel +++ b/example/server/orchestrator/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "orchestrator_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/server/orchestrator", + importpath = "github.com/uber/submitqueue/example/server/orchestrator", visibility = ["//visibility:private"], deps = [ "//orchestrator/controller", diff --git a/examples/server/orchestrator/main.go b/example/server/orchestrator/main.go similarity index 100% rename from examples/server/orchestrator/main.go rename to example/server/orchestrator/main.go diff --git a/examples/server/speculator/BUILD.bazel b/example/server/speculator/BUILD.bazel similarity index 87% rename from examples/server/speculator/BUILD.bazel rename to example/server/speculator/BUILD.bazel index c8f93b7b..dd14ae66 100644 --- a/examples/server/speculator/BUILD.bazel +++ b/example/server/speculator/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "speculator_lib", srcs = ["main.go"], - importpath = "github.com/uber/submitqueue/examples/server/speculator", + importpath = "github.com/uber/submitqueue/example/server/speculator", visibility = ["//visibility:private"], deps = [ "//speculator/controller", diff --git a/examples/server/speculator/main.go b/example/server/speculator/main.go similarity index 100% rename from examples/server/speculator/main.go rename to example/server/speculator/main.go diff --git a/extensions/counter/BUILD.bazel b/extension/counter/BUILD.bazel similarity index 69% rename from extensions/counter/BUILD.bazel rename to extension/counter/BUILD.bazel index cca4640d..ee7a5b31 100644 --- a/extensions/counter/BUILD.bazel +++ b/extension/counter/BUILD.bazel @@ -3,6 +3,6 @@ load("@rules_go//go:def.bzl", "go_library") go_library( name = "counter", srcs = ["counter.go"], - importpath = "github.com/uber/submitqueue/extensions/counter", + importpath = "github.com/uber/submitqueue/extension/counter", visibility = ["//visibility:public"], ) diff --git a/extensions/counter/README.md b/extension/counter/README.md similarity index 86% rename from extensions/counter/README.md rename to extension/counter/README.md index b7464b4e..93a59fc7 100644 --- a/extensions/counter/README.md +++ b/extension/counter/README.md @@ -30,6 +30,6 @@ val, err = cnt.Next(ctx, "request/other") // returns 1 ## Implementing a Backend -1. Create `extensions/counter/{backend}/` directory +1. Create `extension/counter/{backend}/` directory 2. Implement the `Counter` interface -3. Add a schema file under `extensions/counter/{backend}/schema/` if the backend requires it +3. Add a schema file under `extension/counter/{backend}/schema/` if the backend requires it diff --git a/extensions/counter/counter.go b/extension/counter/counter.go similarity index 100% rename from extensions/counter/counter.go rename to extension/counter/counter.go diff --git a/extensions/counter/mysql/BUILD.bazel b/extension/counter/mysql/BUILD.bazel similarity index 61% rename from extensions/counter/mysql/BUILD.bazel rename to extension/counter/mysql/BUILD.bazel index 5fff3464..64b4a0ce 100644 --- a/extensions/counter/mysql/BUILD.bazel +++ b/extension/counter/mysql/BUILD.bazel @@ -3,9 +3,9 @@ load("@rules_go//go:def.bzl", "go_library") go_library( name = "mysql", srcs = ["counter.go"], - importpath = "github.com/uber/submitqueue/extensions/counter/mysql", + importpath = "github.com/uber/submitqueue/extension/counter/mysql", visibility = ["//visibility:public"], deps = [ - "//extensions/counter", + "//extension/counter", ], ) diff --git a/extensions/counter/mysql/counter.go b/extension/counter/mysql/counter.go similarity index 94% rename from extensions/counter/mysql/counter.go rename to extension/counter/mysql/counter.go index 73c471f4..ba72639b 100644 --- a/extensions/counter/mysql/counter.go +++ b/extension/counter/mysql/counter.go @@ -5,7 +5,7 @@ import ( "database/sql" "fmt" - "github.com/uber/submitqueue/extensions/counter" + "github.com/uber/submitqueue/extension/counter" ) type mysqlCounter struct { diff --git a/extensions/counter/mysql/schema/BUILD.bazel b/extension/counter/mysql/schema/BUILD.bazel similarity index 100% rename from extensions/counter/mysql/schema/BUILD.bazel rename to extension/counter/mysql/schema/BUILD.bazel diff --git a/extensions/counter/mysql/schema/counter.sql b/extension/counter/mysql/schema/counter.sql similarity index 100% rename from extensions/counter/mysql/schema/counter.sql rename to extension/counter/mysql/schema/counter.sql diff --git a/extensions/queue/BUILD.bazel b/extension/queue/BUILD.bazel similarity index 70% rename from extensions/queue/BUILD.bazel rename to extension/queue/BUILD.bazel index 4beee766..0251e3b4 100644 --- a/extensions/queue/BUILD.bazel +++ b/extension/queue/BUILD.bazel @@ -8,7 +8,7 @@ go_library( "queue.go", "subscriber.go", ], - importpath = "github.com/uber/submitqueue/extensions/queue", + importpath = "github.com/uber/submitqueue/extension/queue", visibility = ["//visibility:public"], - deps = ["//entities/queue"], + deps = ["//entity/queue"], ) diff --git a/extensions/queue/README.md b/extension/queue/README.md similarity index 96% rename from extensions/queue/README.md rename to extension/queue/README.md index c40dfa7d..17ed31d6 100644 --- a/extensions/queue/README.md +++ b/extension/queue/README.md @@ -65,7 +65,7 @@ for delivery := range deliveries { ## Implementing a Backend -1. Create `extensions/queue/{backend}/` directory +1. Create `extension/queue/{backend}/` directory 2. Implement `Queue`, `Publisher`, `Subscriber`, `Delivery` interfaces 3. Map `queue.Message` to backend format diff --git a/extensions/queue/delivery.go b/extension/queue/delivery.go similarity index 97% rename from extensions/queue/delivery.go rename to extension/queue/delivery.go index 0616f63a..05faca8c 100644 --- a/extensions/queue/delivery.go +++ b/extension/queue/delivery.go @@ -3,7 +3,7 @@ package queue import ( "context" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) // Delivery represents a message delivered by a Subscriber. diff --git a/extensions/queue/publisher.go b/extension/queue/publisher.go similarity index 88% rename from extensions/queue/publisher.go rename to extension/queue/publisher.go index 4a7f0d65..c77adbc9 100644 --- a/extensions/queue/publisher.go +++ b/extension/queue/publisher.go @@ -3,7 +3,7 @@ package queue import ( "context" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) // Publisher publishes messages to topics. diff --git a/extensions/queue/queue.go b/extension/queue/queue.go similarity index 100% rename from extensions/queue/queue.go rename to extension/queue/queue.go diff --git a/extensions/queue/sql/BUILD.bazel b/extension/queue/sql/BUILD.bazel similarity index 86% rename from extensions/queue/sql/BUILD.bazel rename to extension/queue/sql/BUILD.bazel index 7609aa66..5b552d68 100644 --- a/extensions/queue/sql/BUILD.bazel +++ b/extension/queue/sql/BUILD.bazel @@ -16,11 +16,11 @@ go_library( "subscriber.go", "validation.go", ], - importpath = "github.com/uber/submitqueue/extensions/queue/sql", + importpath = "github.com/uber/submitqueue/extension/queue/sql", visibility = ["//visibility:public"], deps = [ - "//entities/queue", - "//extensions/queue", + "//entity/queue", + "//extension/queue", "@com_github_uber_go_tally_v4//:tally", "@org_uber_go_mock//gomock", "@org_uber_go_zap//:zap", @@ -40,8 +40,8 @@ go_test( ], embed = [":sql"], deps = [ - "//entities/queue", - "//extensions/queue", + "//entity/queue", + "//extension/queue", "@com_github_data_dog_go_sqlmock//:go-sqlmock", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/extensions/queue/sql/README.md b/extension/queue/sql/README.md similarity index 95% rename from extensions/queue/sql/README.md rename to extension/queue/sql/README.md index 209d1db4..8c9a9175 100644 --- a/extensions/queue/sql/README.md +++ b/extension/queue/sql/README.md @@ -15,8 +15,8 @@ MySQL-based distributed queue with partition leasing, visibility timeout, and at import ( "database/sql" _ "github.com/go-sql-driver/mysql" - queueSQL "github.com/uber/submitqueue/extensions/queue/sql" - "github.com/uber/submitqueue/entities/queue" + queueSQL "github.com/uber/submitqueue/extension/queue/sql" + "github.com/uber/submitqueue/entity/queue" ) // Setup diff --git a/extensions/queue/sql/config.go b/extension/queue/sql/config.go similarity index 100% rename from extensions/queue/sql/config.go rename to extension/queue/sql/config.go diff --git a/extensions/queue/sql/config_test.go b/extension/queue/sql/config_test.go similarity index 100% rename from extensions/queue/sql/config_test.go rename to extension/queue/sql/config_test.go diff --git a/extensions/queue/sql/constants.go b/extension/queue/sql/constants.go similarity index 100% rename from extensions/queue/sql/constants.go rename to extension/queue/sql/constants.go diff --git a/extensions/queue/sql/errors.go b/extension/queue/sql/errors.go similarity index 100% rename from extensions/queue/sql/errors.go rename to extension/queue/sql/errors.go diff --git a/extensions/queue/sql/message_store.go b/extension/queue/sql/message_store.go similarity index 99% rename from extensions/queue/sql/message_store.go rename to extension/queue/sql/message_store.go index 714c635c..bbccbbaf 100644 --- a/extensions/queue/sql/message_store.go +++ b/extension/queue/sql/message_store.go @@ -10,7 +10,7 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) diff --git a/extensions/queue/sql/message_store_test.go b/extension/queue/sql/message_store_test.go similarity index 99% rename from extensions/queue/sql/message_store_test.go rename to extension/queue/sql/message_store_test.go index a6f7da59..8d0ad38a 100644 --- a/extensions/queue/sql/message_store_test.go +++ b/extension/queue/sql/message_store_test.go @@ -11,7 +11,7 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap/zaptest" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) // testMetrics returns a test metrics scope for use in tests diff --git a/extensions/queue/sql/mock_stores.go b/extension/queue/sql/mock_stores.go similarity index 99% rename from extensions/queue/sql/mock_stores.go rename to extension/queue/sql/mock_stores.go index 7df7d1a7..6d00b04c 100644 --- a/extensions/queue/sql/mock_stores.go +++ b/extension/queue/sql/mock_stores.go @@ -13,7 +13,7 @@ import ( context "context" reflect "reflect" - queue "github.com/uber/submitqueue/entities/queue" + queue "github.com/uber/submitqueue/entity/queue" gomock "go.uber.org/mock/gomock" ) diff --git a/extensions/queue/sql/offset_store.go b/extension/queue/sql/offset_store.go similarity index 100% rename from extensions/queue/sql/offset_store.go rename to extension/queue/sql/offset_store.go diff --git a/extensions/queue/sql/offset_store_test.go b/extension/queue/sql/offset_store_test.go similarity index 100% rename from extensions/queue/sql/offset_store_test.go rename to extension/queue/sql/offset_store_test.go diff --git a/extensions/queue/sql/partition_lease_store.go b/extension/queue/sql/partition_lease_store.go similarity index 100% rename from extensions/queue/sql/partition_lease_store.go rename to extension/queue/sql/partition_lease_store.go diff --git a/extensions/queue/sql/partition_lease_store_test.go b/extension/queue/sql/partition_lease_store_test.go similarity index 100% rename from extensions/queue/sql/partition_lease_store_test.go rename to extension/queue/sql/partition_lease_store_test.go diff --git a/extensions/queue/sql/publisher.go b/extension/queue/sql/publisher.go similarity index 97% rename from extensions/queue/sql/publisher.go rename to extension/queue/sql/publisher.go index 530a24a3..e75a592f 100644 --- a/extensions/queue/sql/publisher.go +++ b/extension/queue/sql/publisher.go @@ -8,7 +8,7 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) type publisher struct { diff --git a/extensions/queue/sql/publisher_test.go b/extension/queue/sql/publisher_test.go similarity index 98% rename from extensions/queue/sql/publisher_test.go rename to extension/queue/sql/publisher_test.go index 2064b121..7add4ba4 100644 --- a/extensions/queue/sql/publisher_test.go +++ b/extension/queue/sql/publisher_test.go @@ -10,8 +10,8 @@ import ( "go.uber.org/mock/gomock" "go.uber.org/zap/zaptest" - "github.com/uber/submitqueue/entities/queue" - extqueue "github.com/uber/submitqueue/extensions/queue" + "github.com/uber/submitqueue/entity/queue" + extqueue "github.com/uber/submitqueue/extension/queue" // mocks in same package ) diff --git a/extensions/queue/sql/schema/BUILD.bazel b/extension/queue/sql/schema/BUILD.bazel similarity index 100% rename from extensions/queue/sql/schema/BUILD.bazel rename to extension/queue/sql/schema/BUILD.bazel diff --git a/extensions/queue/sql/schema/queue_messages.sql b/extension/queue/sql/schema/queue_messages.sql similarity index 100% rename from extensions/queue/sql/schema/queue_messages.sql rename to extension/queue/sql/schema/queue_messages.sql diff --git a/extensions/queue/sql/schema/queue_offsets.sql b/extension/queue/sql/schema/queue_offsets.sql similarity index 100% rename from extensions/queue/sql/schema/queue_offsets.sql rename to extension/queue/sql/schema/queue_offsets.sql diff --git a/extensions/queue/sql/schema/queue_partition_leases.sql b/extension/queue/sql/schema/queue_partition_leases.sql similarity index 100% rename from extensions/queue/sql/schema/queue_partition_leases.sql rename to extension/queue/sql/schema/queue_partition_leases.sql diff --git a/extensions/queue/sql/sql.go b/extension/queue/sql/sql.go similarity index 90% rename from extensions/queue/sql/sql.go rename to extension/queue/sql/sql.go index a5af3b80..259556aa 100644 --- a/extensions/queue/sql/sql.go +++ b/extension/queue/sql/sql.go @@ -8,7 +8,7 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap" - "github.com/uber/submitqueue/extensions/queue" + "github.com/uber/submitqueue/extension/queue" ) type queueImpl struct { @@ -17,7 +17,7 @@ type queueImpl struct { closed bool } -// Params holds dependencies for creating a SQL queue factory +// Params holds dependencies for creating a SQL queue type Params struct { // DB is the database connection (required) DB *sql.DB @@ -32,7 +32,7 @@ type Params struct { Config Config } -// NewQueue creates a new SQL-based queue factory +// NewQueue creates a new SQL-based queue func NewQueue(params Params) (queue.Queue, error) { if err := params.Config.Validate(); err != nil { return nil, fmt.Errorf("invalid config: %w", err) @@ -44,7 +44,7 @@ func NewQueue(params Params) (queue.Queue, error) { } logger := params.Logger.Sugar().Named("queue.sql") - logger.Infow("created SQL queue factory", + logger.Infow("created SQL queue", "consumer_group", params.Config.ConsumerGroup, "worker_id", params.Config.WorkerID, "poll_interval", params.Config.PollInterval, @@ -92,7 +92,7 @@ func (q *queueImpl) Subscriber() queue.Subscriber { return q.subscriber } -// Close shuts down the factory and all associated resources +// Close shuts down the queue and all associated resources func (q *queueImpl) Close() error { if q.closed { return nil diff --git a/extensions/queue/sql/sql_test.go b/extension/queue/sql/sql_test.go similarity index 77% rename from extensions/queue/sql/sql_test.go rename to extension/queue/sql/sql_test.go index b07cf2b1..f1b4bb38 100644 --- a/extensions/queue/sql/sql_test.go +++ b/extension/queue/sql/sql_test.go @@ -10,7 +10,7 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap/zaptest" - "github.com/uber/submitqueue/extensions/queue" + "github.com/uber/submitqueue/extension/queue" ) func TestNewQueue(t *testing.T) { @@ -21,7 +21,7 @@ func TestNewQueue(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -29,11 +29,11 @@ func TestNewQueue(t *testing.T) { }) require.NoError(t, err) - require.NotNil(t, factory) - assert.NotNil(t, factory.Publisher()) - assert.NotNil(t, factory.Subscriber()) + require.NotNil(t, q) + assert.NotNil(t, q.Publisher()) + assert.NotNil(t, q.Subscriber()) - err = factory.Close() + err = q.Close() assert.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) @@ -46,7 +46,7 @@ func TestNewQueue(t *testing.T) { config := DefaultConfig("", "") // Invalid: empty consumer group and worker ID - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -54,7 +54,7 @@ func TestNewQueue(t *testing.T) { }) require.Error(t, err) - assert.Nil(t, factory) + assert.Nil(t, q) }) t.Run("error when DB ping fails", func(t *testing.T) { @@ -64,7 +64,7 @@ func TestNewQueue(t *testing.T) { mock.ExpectPing().WillReturnError(sql.ErrConnDone) - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -72,7 +72,7 @@ func TestNewQueue(t *testing.T) { }) require.Error(t, err) - assert.Nil(t, factory) + assert.Nil(t, q) require.NoError(t, mock.ExpectationsWereMet()) }) @@ -85,21 +85,21 @@ func TestQueue_Publisher(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), Config: DefaultConfig("test-consumer", "test-worker"), }) require.NoError(t, err) - defer factory.Close() + defer q.Close() // First call creates publisher - pub1 := factory.Publisher() + pub1 := q.Publisher() assert.NotNil(t, pub1) // Second call returns same publisher (singleton) - pub2 := factory.Publisher() + pub2 := q.Publisher() assert.Equal(t, pub1, pub2) require.NoError(t, mock.ExpectationsWereMet()) @@ -112,21 +112,21 @@ func TestQueue_Subscriber(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), Config: DefaultConfig("test-consumer", "test-worker"), }) require.NoError(t, err) - defer factory.Close() + defer q.Close() // First call creates subscriber - sub1 := factory.Subscriber() + sub1 := q.Subscriber() assert.NotNil(t, sub1) // Second call returns same subscriber (singleton) - sub2 := factory.Subscriber() + sub2 := q.Subscriber() assert.Equal(t, sub1, sub2) require.NoError(t, mock.ExpectationsWereMet()) @@ -134,34 +134,34 @@ func TestQueue_Subscriber(t *testing.T) { func TestQueue_Close(t *testing.T) { tests := []struct { - name string - setupFactory func(t *testing.T, f queue.Queue) - wantErr bool + name string + setupQueue func(t *testing.T, q queue.Queue) + wantErr bool }{ { - name: "close without creating publisher or subscriber", - setupFactory: func(t *testing.T, f queue.Queue) {}, - wantErr: false, + name: "close without creating publisher or subscriber", + setupQueue: func(t *testing.T, q queue.Queue) {}, + wantErr: false, }, { name: "close after creating publisher", - setupFactory: func(t *testing.T, f queue.Queue) { - _ = f.Publisher() + setupQueue: func(t *testing.T, q queue.Queue) { + _ = q.Publisher() }, wantErr: false, }, { name: "close after creating subscriber", - setupFactory: func(t *testing.T, f queue.Queue) { - _ = f.Subscriber() + setupQueue: func(t *testing.T, q queue.Queue) { + _ = q.Subscriber() }, wantErr: false, }, { name: "close after creating both publisher and subscriber", - setupFactory: func(t *testing.T, f queue.Queue) { - _ = f.Publisher() - _ = f.Subscriber() + setupQueue: func(t *testing.T, q queue.Queue) { + _ = q.Publisher() + _ = q.Subscriber() }, wantErr: false, }, @@ -175,7 +175,7 @@ func TestQueue_Close(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -183,11 +183,11 @@ func TestQueue_Close(t *testing.T) { }) require.NoError(t, err) - // Setup factory state - tt.setupFactory(t, factory) + // Setup queue state + tt.setupQueue(t, q) - // Close factory - err = factory.Close() + // Close queue + err = q.Close() if tt.wantErr { assert.Error(t, err) } else { @@ -205,7 +205,7 @@ func TestQueue_Close(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -214,10 +214,10 @@ func TestQueue_Close(t *testing.T) { require.NoError(t, err) // Close multiple times - err = factory.Close() + err = q.Close() assert.NoError(t, err) - err = factory.Close() + err = q.Close() assert.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) @@ -230,7 +230,7 @@ func TestQueue_Close(t *testing.T) { mock.ExpectPing() - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: zaptest.NewLogger(t), MetricsScope: tally.NewTestScope("test", nil), @@ -239,16 +239,16 @@ func TestQueue_Close(t *testing.T) { require.NoError(t, err) // Create publisher before close - pub := factory.Publisher() + pub := q.Publisher() assert.NotNil(t, pub) - // Close factory - err = factory.Close() + // Close queue + err = q.Close() assert.NoError(t, err) // Getting publisher/subscriber after close should return the same instances // (they were already created, so singleton pattern returns them) - pub2 := factory.Publisher() + pub2 := q.Publisher() assert.Equal(t, pub, pub2, "should return same publisher instance after close") require.NoError(t, mock.ExpectationsWereMet()) @@ -266,28 +266,28 @@ func TestQueue_Integration(t *testing.T) { metricsScope := tally.NewTestScope("test", nil) config := DefaultConfig("test-consumer", "test-worker") - factory, err := NewQueue(Params{ + q, err := NewQueue(Params{ DB: db, Logger: logger, MetricsScope: metricsScope, Config: config, }) require.NoError(t, err) - defer factory.Close() + defer q.Close() // Verify we can get both publisher and subscriber - publisher := factory.Publisher() - subscriber := factory.Subscriber() + publisher := q.Publisher() + subscriber := q.Subscriber() assert.NotNil(t, publisher) assert.NotNil(t, subscriber) // Verify they're singletons - assert.Equal(t, publisher, factory.Publisher()) - assert.Equal(t, subscriber, factory.Subscriber()) + assert.Equal(t, publisher, q.Publisher()) + assert.Equal(t, subscriber, q.Subscriber()) // Close should succeed - err = factory.Close() + err = q.Close() assert.NoError(t, err) require.NoError(t, mock.ExpectationsWereMet()) diff --git a/extensions/queue/sql/stores.go b/extension/queue/sql/stores.go similarity index 99% rename from extensions/queue/sql/stores.go rename to extension/queue/sql/stores.go index b46a7fcc..aa9deb4c 100644 --- a/extensions/queue/sql/stores.go +++ b/extension/queue/sql/stores.go @@ -5,7 +5,7 @@ package sql import ( "context" - "github.com/uber/submitqueue/entities/queue" + "github.com/uber/submitqueue/entity/queue" ) const ( diff --git a/extensions/queue/sql/subscriber.go b/extension/queue/sql/subscriber.go similarity index 99% rename from extensions/queue/sql/subscriber.go rename to extension/queue/sql/subscriber.go index 0b31128e..eaf7b042 100644 --- a/extensions/queue/sql/subscriber.go +++ b/extension/queue/sql/subscriber.go @@ -10,8 +10,8 @@ import ( "github.com/uber-go/tally/v4" "go.uber.org/zap" - "github.com/uber/submitqueue/entities/queue" - extqueue "github.com/uber/submitqueue/extensions/queue" + "github.com/uber/submitqueue/entity/queue" + extqueue "github.com/uber/submitqueue/extension/queue" ) type subscriber struct { diff --git a/extensions/queue/sql/subscriber_test.go b/extension/queue/sql/subscriber_test.go similarity index 98% rename from extensions/queue/sql/subscriber_test.go rename to extension/queue/sql/subscriber_test.go index cf97491d..1532db4d 100644 --- a/extensions/queue/sql/subscriber_test.go +++ b/extension/queue/sql/subscriber_test.go @@ -10,7 +10,7 @@ import ( "go.uber.org/mock/gomock" "go.uber.org/zap/zaptest" - extqueue "github.com/uber/submitqueue/extensions/queue" + extqueue "github.com/uber/submitqueue/extension/queue" ) func setupSubscriberTest(t *testing.T, mockMessageStore *MockmessageStore, mockOffsetStore *MockoffsetStore, mockLeaseStore *MockpartitionLeaseStore) extqueue.Subscriber { diff --git a/extensions/queue/sql/validation.go b/extension/queue/sql/validation.go similarity index 100% rename from extensions/queue/sql/validation.go rename to extension/queue/sql/validation.go diff --git a/extensions/queue/subscriber.go b/extension/queue/subscriber.go similarity index 100% rename from extensions/queue/subscriber.go rename to extension/queue/subscriber.go diff --git a/extensions/storage/BUILD.bazel b/extension/storage/BUILD.bazel similarity index 67% rename from extensions/storage/BUILD.bazel rename to extension/storage/BUILD.bazel index efab6747..8d6b95f0 100644 --- a/extensions/storage/BUILD.bazel +++ b/extension/storage/BUILD.bazel @@ -6,7 +6,7 @@ go_library( "request_store.go", "storage.go", ], - importpath = "github.com/uber/submitqueue/extensions/storage", + importpath = "github.com/uber/submitqueue/extension/storage", visibility = ["//visibility:public"], - deps = ["//entities"], + deps = ["//entity"], ) diff --git a/extensions/storage/mysql/BUILD.bazel b/extension/storage/mysql/BUILD.bazel similarity index 61% rename from extensions/storage/mysql/BUILD.bazel rename to extension/storage/mysql/BUILD.bazel index e026f665..d17f705f 100644 --- a/extensions/storage/mysql/BUILD.bazel +++ b/extension/storage/mysql/BUILD.bazel @@ -3,14 +3,14 @@ load("@rules_go//go:def.bzl", "go_library") go_library( name = "mysql", srcs = [ - "factory.go", + "storage.go", "request_store.go", ], - importpath = "github.com/uber/submitqueue/extensions/storage/mysql", + importpath = "github.com/uber/submitqueue/extension/storage/mysql", visibility = ["//visibility:public"], deps = [ - "//entities", - "//extensions/storage", + "//entity", + "//extension/storage", "@com_github_go_sql_driver_mysql//:mysql", ], ) diff --git a/extensions/storage/mysql/request_store.go b/extension/storage/mysql/request_store.go similarity index 85% rename from extensions/storage/mysql/request_store.go rename to extension/storage/mysql/request_store.go index a38afde2..8f9841a8 100644 --- a/extensions/storage/mysql/request_store.go +++ b/extension/storage/mysql/request_store.go @@ -9,8 +9,8 @@ import ( "github.com/go-sql-driver/mysql" - "github.com/uber/submitqueue/entities" - "github.com/uber/submitqueue/extensions/storage" + "github.com/uber/submitqueue/entity" + "github.com/uber/submitqueue/extension/storage" ) type requestStore struct { @@ -23,8 +23,8 @@ func NewRequestStore(db *sql.DB) storage.RequestStore { } // Get retrieves a land request by ID. Returns ErrNotFound if the request is not found. -func (r *requestStore) Get(ctx context.Context, id string) (entities.Request, error) { - var req entities.Request +func (r *requestStore) Get(ctx context.Context, id string) (entity.Request, error) { + var req entity.Request var changeIDsJSON []byte err := r.db.QueryRowContext(ctx, @@ -33,21 +33,21 @@ func (r *requestStore) Get(ctx context.Context, id string) (entities.Request, er ).Scan(&req.ID, &req.Queue, &req.Change.Source, &changeIDsJSON, &req.LandStrategy, &req.State, &req.Version) if errors.Is(err, sql.ErrNoRows) { - return entities.Request{}, storage.WrapNotFound(err) + return entity.Request{}, storage.WrapNotFound(err) } if err != nil { - return entities.Request{}, fmt.Errorf("failed to get request entity id=%s from the database: %w", id, err) + return entity.Request{}, fmt.Errorf("failed to get request entity id=%s from the database: %w", id, err) } if err := json.Unmarshal(changeIDsJSON, &req.Change.IDs); err != nil { - return entities.Request{}, fmt.Errorf("failed to unmarshal change IDs for request entity id=%s from the database: %w", id, err) + return entity.Request{}, fmt.Errorf("failed to unmarshal change IDs for request entity id=%s from the database: %w", id, err) } return req, nil } // Create creates a new land request. The request must have a unique ID already assigned. Returns ErrAlreadyExists if the request ID already exists. -func (r *requestStore) Create(ctx context.Context, request entities.Request) error { +func (r *requestStore) Create(ctx context.Context, request entity.Request) error { changeIDsJSON, err := json.Marshal(request.Change.IDs) if err != nil { return fmt.Errorf("failed to marshal change IDs=%v id=%s for Create request entity: %w", request.Change.IDs, request.ID, err) @@ -72,7 +72,7 @@ func (r *requestStore) Create(ctx context.Context, request entities.Request) err // UpdateState updates the state of a land request if the current version matches the expected version. If versions do not match, returns ErrVersionMismatch. // The implementation increments the version by 1 atomically with the state update. -func (r *requestStore) UpdateState(ctx context.Context, id string, version int32, newState entities.RequestState) error { +func (r *requestStore) UpdateState(ctx context.Context, id string, version int32, newState entity.RequestState) error { result, err := r.db.ExecContext(ctx, "UPDATE request SET state = ?, version = version + 1 WHERE id = ? AND version = ?", newState, id, version, diff --git a/extensions/storage/mysql/schema/BUILD.bazel b/extension/storage/mysql/schema/BUILD.bazel similarity index 100% rename from extensions/storage/mysql/schema/BUILD.bazel rename to extension/storage/mysql/schema/BUILD.bazel diff --git a/extensions/storage/mysql/schema/request.sql b/extension/storage/mysql/schema/request.sql similarity index 100% rename from extensions/storage/mysql/schema/request.sql rename to extension/storage/mysql/schema/request.sql diff --git a/extensions/storage/mysql/factory.go b/extension/storage/mysql/storage.go similarity index 81% rename from extensions/storage/mysql/factory.go rename to extension/storage/mysql/storage.go index cf8d586c..b2b8e8ca 100644 --- a/extensions/storage/mysql/factory.go +++ b/extension/storage/mysql/storage.go @@ -7,10 +7,10 @@ import ( _ "github.com/go-sql-driver/mysql" - "github.com/uber/submitqueue/extensions/storage" + "github.com/uber/submitqueue/extension/storage" ) -// MySQLParameters defines the configuration for the MySQL storage factory. +// MySQLParameters defines the configuration for the MySQL storage. // TODO: integrate with configuration system. type MySQLParameters struct { // DSN is the MySQL Data Source Name. @@ -27,13 +27,13 @@ type MySQLParameters struct { ConnMaxLifetime time.Duration } -type factory struct { +type mysqlStorage struct { db *sql.DB requestStore storage.RequestStore } -// NewFactory creates a new MySQL storage factory. -func NewFactory(p MySQLParameters) (storage.StoreFactory, error) { +// NewStorage creates a new MySQL storage. +func NewStorage(p MySQLParameters) (storage.Storage, error) { db, err := sql.Open("mysql", p.DSN) if err != nil { return nil, fmt.Errorf("failed to open MySQL connection: %w", err) @@ -49,18 +49,18 @@ func NewFactory(p MySQLParameters) (storage.StoreFactory, error) { db.SetConnMaxLifetime(p.ConnMaxLifetime) } - return &factory{ + return &mysqlStorage{ db: db, requestStore: NewRequestStore(db), }, nil } // GetRequestStore returns the MySQL-backed RequestStore. -func (f *factory) GetRequestStore() storage.RequestStore { +func (f *mysqlStorage) GetRequestStore() storage.RequestStore { return f.requestStore } // Close closes the underlying database connection. -func (f *factory) Close() error { +func (f *mysqlStorage) Close() error { return f.db.Close() } diff --git a/extensions/storage/request_store.go b/extension/storage/request_store.go similarity index 78% rename from extensions/storage/request_store.go rename to extension/storage/request_store.go index 84424ae2..bb84fb3e 100644 --- a/extensions/storage/request_store.go +++ b/extension/storage/request_store.go @@ -3,19 +3,19 @@ package storage import ( "context" - "github.com/uber/submitqueue/entities" + "github.com/uber/submitqueue/entity" ) // RequestStore is an interface that defines methods for managing land requests in the database. type RequestStore interface { // Get retrieves a land request by ID. Returns ErrNotFound if the request is not found. - Get(ctx context.Context, id string) (entities.Request, error) + Get(ctx context.Context, id string) (entity.Request, error) // Create creates a new land request. The request must have a unique ID already assigned. // Returns ErrAlreadyExists if a request with the same ID already exists. - Create(ctx context.Context, request entities.Request) error + Create(ctx context.Context, request entity.Request) error // UpdateState updates the state of a land request if the current version matches the expected version. If versions do not match, returns ErrVersionMismatch. // The implementation should increment the version by 1 atomically with the state update. - UpdateState(ctx context.Context, id string, version int32, newState entities.RequestState) error + UpdateState(ctx context.Context, id string, version int32, newState entity.RequestState) error } diff --git a/extensions/storage/storage.go b/extension/storage/storage.go similarity index 74% rename from extensions/storage/storage.go rename to extension/storage/storage.go index d10a16e2..ab57d004 100644 --- a/extensions/storage/storage.go +++ b/extension/storage/storage.go @@ -24,12 +24,11 @@ var ErrAlreadyExists = errors.New("record already exists") // and either retry or implement idempotent operations. var ErrVersionMismatch = errors.New("version mismatch") -// StoreFactory is an interface that defines methods for creating different stores.. -// Each store is responsible for performing atomic storage operations for a specific entity type. -type StoreFactory interface { - // GetRequestStore creates a new RequestStore instance. +// Storage is a factory interface that aggregates all entity stores into a single injectable dependency. +type Storage interface { + // GetRequestStore returns the RequestStore instance. GetRequestStore() RequestStore - // Close closes the store factory and all underlying connections. Should only be called once at the end of the program. + // Close closes the storage and all underlying connections. Should only be called once at the end of the program. Close() error } diff --git a/gateway/controller/BUILD.bazel b/gateway/controller/BUILD.bazel index 916c3cd2..6493d9cd 100644 --- a/gateway/controller/BUILD.bazel +++ b/gateway/controller/BUILD.bazel @@ -9,9 +9,9 @@ go_library( importpath = "github.com/uber/submitqueue/gateway/controller", visibility = ["//visibility:public"], deps = [ - "//entities", - "//extensions/counter", - "//extensions/storage", + "//entity", + "//extension/counter", + "//extension/storage", "//gateway/protopb", "@com_github_uber_go_tally_v4//:tally", "@org_uber_go_zap//:zap", @@ -26,8 +26,8 @@ go_test( ], embed = [":controller"], deps = [ - "//entities", - "//extensions/storage", + "//entity", + "//extension/storage", "//gateway/protopb", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/gateway/controller/land.go b/gateway/controller/land.go index bff23d9a..83a840c4 100644 --- a/gateway/controller/land.go +++ b/gateway/controller/land.go @@ -6,9 +6,9 @@ import ( "time" "github.com/uber-go/tally/v4" - "github.com/uber/submitqueue/entities" - "github.com/uber/submitqueue/extensions/counter" - "github.com/uber/submitqueue/extensions/storage" + "github.com/uber/submitqueue/entity" + "github.com/uber/submitqueue/extension/counter" + "github.com/uber/submitqueue/extension/storage" pb "github.com/uber/submitqueue/gateway/protopb" "go.uber.org/zap" ) @@ -17,16 +17,16 @@ import ( type LandController struct { logger *zap.Logger metricsScope tally.Scope - storeFactory storage.StoreFactory + store storage.Storage counter counter.Counter } // NewLandController creates a new instance of the gateway land controller -func NewLandController(logger *zap.Logger, scope tally.Scope, storeFactory storage.StoreFactory, counter counter.Counter) *LandController { +func NewLandController(logger *zap.Logger, scope tally.Scope, store storage.Storage, counter counter.Counter) *LandController { return &LandController{ logger: logger, metricsScope: scope, - storeFactory: storeFactory, + store: store, counter: counter, } } @@ -40,7 +40,7 @@ func (c *LandController) Land(ctx context.Context, req *pb.LandRequest) (*pb.Lan c.metricsScope.Counter("land_request_count").Inc(1) - change := entities.Change{ + change := entity.Change{ Source: req.Change.GetSource(), IDs: req.Change.GetIds(), } @@ -60,16 +60,16 @@ func (c *LandController) Land(ctx context.Context, req *pb.LandRequest) (*pb.Lan return nil, fmt.Errorf("LandController failed to generate request ID for queue=%s: %w", queue, err) } - request := entities.Request{ + request := entity.Request{ ID: fmt.Sprintf("%s/%d", queue, seq), Queue: queue, Change: change, LandStrategy: strategy, - State: entities.RequestStateNew, + State: entity.RequestStateNew, Version: 1, } - if err := c.storeFactory.GetRequestStore().Create(ctx, request); err != nil { + if err := c.store.GetRequestStore().Create(ctx, request); err != nil { return nil, fmt.Errorf("LandController failed to create request for queue=%s: %w", req.Queue, err) } @@ -84,18 +84,18 @@ func (c *LandController) Land(ctx context.Context, req *pb.LandRequest) (*pb.Lan } // protoStrategyToEntity maps a proto Strategy enum to the entity RequestLandStrategy. -func resolveRequestLandStrategy(s pb.Strategy) (entities.RequestLandStrategy, error) { +func resolveRequestLandStrategy(s pb.Strategy) (entity.RequestLandStrategy, error) { switch s { case pb.Strategy_DEFAULT: // TODO: resolve default strategy based on queue configuration - return entities.RequestLandStrategyRebase, nil + return entity.RequestLandStrategyRebase, nil case pb.Strategy_REBASE: - return entities.RequestLandStrategyRebase, nil + return entity.RequestLandStrategyRebase, nil case pb.Strategy_SQUASH_REBASE: - return entities.RequestLandStrategySquashRebase, nil + return entity.RequestLandStrategySquashRebase, nil case pb.Strategy_MERGE: - return entities.RequestLandStrategyMerge, nil + return entity.RequestLandStrategyMerge, nil default: - return entities.RequestLandStrategyUnknown, fmt.Errorf("unknown proto strategy: %v", s) + return entity.RequestLandStrategyUnknown, fmt.Errorf("unknown proto strategy: %v", s) } } diff --git a/gateway/controller/land_test.go b/gateway/controller/land_test.go index bc2662d9..46b78a53 100644 --- a/gateway/controller/land_test.go +++ b/gateway/controller/land_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/uber-go/tally/v4" - "github.com/uber/submitqueue/entities" - "github.com/uber/submitqueue/extensions/storage" + "github.com/uber/submitqueue/entity" + "github.com/uber/submitqueue/extension/storage" pb "github.com/uber/submitqueue/gateway/protopb" "go.uber.org/zap" ) @@ -23,56 +23,56 @@ func (m *mockCounter) Next(ctx context.Context, domain string) (int64, error) { } type mockRequestStore struct { - createFunc func(ctx context.Context, request entities.Request) error + createFunc func(ctx context.Context, request entity.Request) error } -func (m *mockRequestStore) Get(ctx context.Context, id string) (entities.Request, error) { - return entities.Request{}, nil +func (m *mockRequestStore) Get(ctx context.Context, id string) (entity.Request, error) { + return entity.Request{}, nil } -func (m *mockRequestStore) Create(ctx context.Context, request entities.Request) error { +func (m *mockRequestStore) Create(ctx context.Context, request entity.Request) error { return m.createFunc(ctx, request) } -func (m *mockRequestStore) UpdateState(ctx context.Context, id string, version int32, newState entities.RequestState) error { +func (m *mockRequestStore) UpdateState(ctx context.Context, id string, version int32, newState entity.RequestState) error { return nil } -type mockStoreFactory struct { +type mockStorage struct { requestStore storage.RequestStore } -func (m *mockStoreFactory) GetRequestStore() storage.RequestStore { +func (m *mockStorage) GetRequestStore() storage.RequestStore { return m.requestStore } -func (m *mockStoreFactory) Close() error { +func (m *mockStorage) Close() error { return nil } func TestNewLandController(t *testing.T) { - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { return nil }, }} cnt := &mockCounter{nextFunc: func(ctx context.Context, domain string) (int64, error) { return 1, nil }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) require.NotNil(t, controller) } func TestLand_ReturnsSqid(t *testing.T) { - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { return nil }, }} cnt := &mockCounter{nextFunc: func(ctx context.Context, domain string) (int64, error) { return 1, nil }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) ctx := context.Background() req := &pb.LandRequest{ @@ -86,10 +86,10 @@ func TestLand_ReturnsSqid(t *testing.T) { } func TestLand_PassesCorrectParametersToStore(t *testing.T) { - var capturedRequest entities.Request + var capturedRequest entity.Request - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { capturedRequest = request return nil }, @@ -97,7 +97,7 @@ func TestLand_PassesCorrectParametersToStore(t *testing.T) { cnt := &mockCounter{nextFunc: func(ctx context.Context, domain string) (int64, error) { return 42, nil }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) ctx := context.Background() req := &pb.LandRequest{ @@ -112,22 +112,22 @@ func TestLand_PassesCorrectParametersToStore(t *testing.T) { assert.Equal(t, "my-queue", capturedRequest.Queue) assert.Equal(t, "github", capturedRequest.Change.Source) assert.Equal(t, []string{"pr-1", "pr-2"}, capturedRequest.Change.IDs) - assert.Equal(t, entities.RequestLandStrategyRebase, capturedRequest.LandStrategy) - assert.Equal(t, entities.RequestStateNew, capturedRequest.State) + assert.Equal(t, entity.RequestLandStrategyRebase, capturedRequest.LandStrategy) + assert.Equal(t, entity.RequestStateNew, capturedRequest.State) assert.Equal(t, int32(1), capturedRequest.Version) assert.Equal(t, "my-queue/42", resp.Sqid) } func TestLand_ReturnsErrorOnStorageFailure(t *testing.T) { - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { return fmt.Errorf("database connection failed") }, }} cnt := &mockCounter{nextFunc: func(ctx context.Context, domain string) (int64, error) { return 1, nil }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) ctx := context.Background() req := &pb.LandRequest{ @@ -140,15 +140,15 @@ func TestLand_ReturnsErrorOnStorageFailure(t *testing.T) { } func TestLand_ReturnsErrorOnCounterFailure(t *testing.T) { - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { return nil }, }} cnt := &mockCounter{nextFunc: func(ctx context.Context, domain string) (int64, error) { return 0, fmt.Errorf("counter unavailable") }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) ctx := context.Background() req := &pb.LandRequest{ @@ -163,8 +163,8 @@ func TestLand_ReturnsErrorOnCounterFailure(t *testing.T) { func TestLand_CounterDomainIncludesQueue(t *testing.T) { var capturedDomain string - factory := &mockStoreFactory{requestStore: &mockRequestStore{ - createFunc: func(ctx context.Context, request entities.Request) error { + store := &mockStorage{requestStore: &mockRequestStore{ + createFunc: func(ctx context.Context, request entity.Request) error { return nil }, }} @@ -172,7 +172,7 @@ func TestLand_CounterDomainIncludesQueue(t *testing.T) { capturedDomain = domain return 1, nil }} - controller := NewLandController(zap.NewNop(), tally.NoopScope, factory, cnt) + controller := NewLandController(zap.NewNop(), tally.NoopScope, store, cnt) ctx := context.Background() req := &pb.LandRequest{ diff --git a/gateway/integration_tests/BUILD.bazel b/gateway/integration_test/BUILD.bazel similarity index 91% rename from gateway/integration_tests/BUILD.bazel rename to gateway/integration_test/BUILD.bazel index 774c8243..19d8d845 100644 --- a/gateway/integration_tests/BUILD.bazel +++ b/gateway/integration_test/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_test") go_test( - name = "integration_tests_test", + name = "integration_test_test", srcs = ["ping_test.go"], tags = [ "integration", diff --git a/gateway/integration_tests/ping_test.go b/gateway/integration_test/ping_test.go similarity index 100% rename from gateway/integration_tests/ping_test.go rename to gateway/integration_test/ping_test.go diff --git a/orchestrator/integration_tests/BUILD.bazel b/orchestrator/integration_test/BUILD.bazel similarity index 91% rename from orchestrator/integration_tests/BUILD.bazel rename to orchestrator/integration_test/BUILD.bazel index 0114fda2..545fa60c 100644 --- a/orchestrator/integration_tests/BUILD.bazel +++ b/orchestrator/integration_test/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_test") go_test( - name = "integration_tests_test", + name = "integration_test_test", srcs = ["ping_test.go"], tags = [ "integration", diff --git a/orchestrator/integration_tests/ping_test.go b/orchestrator/integration_test/ping_test.go similarity index 100% rename from orchestrator/integration_tests/ping_test.go rename to orchestrator/integration_test/ping_test.go diff --git a/speculator/integration_tests/BUILD.bazel b/speculator/integration_test/BUILD.bazel similarity index 91% rename from speculator/integration_tests/BUILD.bazel rename to speculator/integration_test/BUILD.bazel index e7d5d4b3..bc9b096d 100644 --- a/speculator/integration_tests/BUILD.bazel +++ b/speculator/integration_test/BUILD.bazel @@ -3,7 +3,7 @@ load("@rules_go//go:def.bzl", "go_test") go_test( - name = "integration_tests_test", + name = "integration_test_test", srcs = ["ping_test.go"], tags = [ "integration", diff --git a/speculator/integration_tests/ping_test.go b/speculator/integration_test/ping_test.go similarity index 100% rename from speculator/integration_tests/ping_test.go rename to speculator/integration_test/ping_test.go diff --git a/tools/BUILD.bazel b/tool/BUILD.bazel similarity index 100% rename from tools/BUILD.bazel rename to tool/BUILD.bazel diff --git a/tools/README.md b/tool/README.md similarity index 70% rename from tools/README.md rename to tool/README.md index 9f019e08..2b0910cc 100644 --- a/tools/README.md +++ b/tool/README.md @@ -4,7 +4,7 @@ This directory contains tooling scripts and configurations for the submitqueue r ## Bazel Wrapper -The `tools/bazel` script is a Python-based Bazelisk implementation that: +The `tool/bazel` script is a Python-based Bazelisk implementation that: - Reads `.bazelversion` from the repository root - Automatically downloads and caches the correct Bazel version - Delegates all commands to that version @@ -13,9 +13,9 @@ The `tools/bazel` script is a Python-based Bazelisk implementation that: ```bash # Use the wrapper directly -./tools/bazel build //... +./tool/bazel build //... -# Or add tools/ to your PATH (via .envrc with direnv) +# Or add tool/ to your PATH (via .envrc with direnv) bazel build //... ``` @@ -27,11 +27,11 @@ The Bazel version is controlled by `.bazelversion` at the repository root. Updat When adding new tools to this directory: -1. Create the script in `tools/` -2. Make it executable: `chmod +x tools/` -3. Add it to `tools/BUILD.bazel` if it needs to be referenced by Bazel rules +1. Create the script in `tool/` +2. Make it executable: `chmod +x tool/` +3. Add it to `tool/BUILD.bazel` if it needs to be referenced by Bazel rules 4. Document it in this README ## Environment Setup -This directory is added to PATH via `.envrc` (for direnv users), allowing you to run `bazel` commands without prefixing with `./tools/`. +This directory is added to PATH via `.envrc` (for direnv users), allowing you to run `bazel` commands without prefixing with `./tool/`. diff --git a/tools/bazel b/tool/bazel similarity index 98% rename from tools/bazel rename to tool/bazel index bab7638a..27e58ac9 100755 --- a/tools/bazel +++ b/tool/bazel @@ -56,7 +56,7 @@ BAZEL_GCS_PATH_PATTERN = ( SUPPORTED_PLATFORMS = {"linux": "linux", "windows": "windows", "darwin": "macos"} -TOOLS_BAZEL_PATH = "./tools/bazel" +TOOLS_BAZEL_PATH = "./tool/bazel" BAZEL_REAL = "BAZEL_REAL" @@ -114,7 +114,7 @@ def decide_which_bazel_version_to_use(): # nightly. (TODO) # - env var "USE_CANARY_BAZEL" or "USE_BAZEL_CANARY" is set -> latest # rc. (TODO) - # - the file workspace_root/tools/bazel exists -> that version. (TODO) + # - the file workspace_root/tool/bazel exists -> that version. (TODO) # - workspace_root/.bazelversion exists -> read contents, that version. # - workspace_root/WORKSPACE contains a version -> that version. (TODO) # - fallback: latest release @@ -446,7 +446,7 @@ def maybe_makedirs(path): def delegate_tools_bazel(bazel_path): """Match Bazel's own delegation behavior in the builds distributed by most - package managers: use tools/bazel if it's present, executable, and not this + package managers: use tool/bazel if it's present, executable, and not this script. """ root = find_workspace_root()