diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d50cdf57 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +# Flags for production build +BUILD_FLAGS := -ldflags="-s -w" -trimpath -buildvcs=false -tags=performance + +# Flags for test build (debugging, race detection, and more) +TEST_BUILD_FLAGS := -race -gcflags=all="-N -l" -trimpath -tags=debug + +# Default target: build for production +all: build + +# Build production binary (optimized for runtime speed and size) +build: + go build $(BUILD_FLAGS) -o bin/percona-mongolink . + +# Build test binary with race detection and debugging enabled +test-build: + go build $(TEST_BUILD_FLAGS) -o bin/percona-mongolink_test . + +# Run tests with race detection +test: + go test -race ./... + +pytest: + poetry run pytest + +lint: + golangci-lint run + +# Clean generated files +clean: + rm -rf bin/* + go clean -cache -testcache + +.PHONY: all build test-build test clean diff --git a/README.md b/README.md index ae9893d8..ba5e4f3e 100644 --- a/README.md +++ b/README.md @@ -28,25 +28,24 @@ Percona MongoLink is a tool for replicating data from a source MongoDB cluster t cd percona-mongolink ``` -2. Build the project: +2. Build the project using the Makefile: ```sh - go build -o bin/mongolink . + make build ``` Alternatively, you can install MongoLink from the cloned repo using `go install`: -```sh -go install . -``` - + ```sh + go install . + ``` This will install `percona-mongolink` into your `GOBIN` directory. If `GOBIN` is included in your `PATH`, you can run MongoLink by simply typing `percona-mongolink` in your terminal. 3. Run the server: ```sh - bin/mongolink --source --target + bin/percona-mongolink --source --target ``` Alternatively, you can use environment variables: @@ -54,7 +53,7 @@ This will install `percona-mongolink` into your `GOBIN` directory. If `GOBIN` is ```sh export SOURCE_URI= export TARGET_URI= - bin/mongolink --source $SOURCE_URI --target $TARGET_URI + bin/percona-mongolink --source $SOURCE_URI --target $TARGET_URI ``` **Note:** Connections to the source and target must have `readPreference=primary` and `writeConcern=majority` explicitly or unset. @@ -68,17 +67,17 @@ To start the replication process, you can either use the command-line interface #### Using Command-Line Interface ```sh -bin/mongolink start +bin/percona-mongolink start ``` #### Using HTTP API -```sh -curl -X POST http://localhost:2242/start -d '{ - "includeNamespaces": ["db1.collection1", "db2.collection2"], - "excludeNamespaces": ["db3.collection3"] -}' -``` + ```sh + curl -X POST http://localhost:2242/start -d '{ + "includeNamespaces": ["db1.collection1", "db2.collection2"], + "excludeNamespaces": ["db3.collection3"] + }' + ``` ### Finalizing the Replication @@ -86,15 +85,15 @@ To finalize the replication process, you can either use the command-line interfa #### Using Command-Line Interface -```sh -bin/mongolink finalize -``` + ```sh + bin/percona-mongolink finalize + ``` #### Using HTTP API -```sh -curl -X POST http://localhost:2242/finalize -``` + ```sh + curl -X POST http://localhost:2242/finalize + ``` ### Pausing the Replication @@ -102,15 +101,15 @@ To pause the replication process, you can either use the command-line interface #### Using Command-Line Interface -```sh -bin/mongolink pause -``` + ```sh + bin/percona-mongolink pause + ``` #### Using HTTP API -```sh -curl -X POST http://localhost:2242/pause -``` + ```sh + curl -X POST http://localhost:2242/pause + ``` ### Resuming the Replication @@ -118,15 +117,15 @@ To resume the replication process, you can either use the command-line interface #### Using Command-Line Interface -```sh -bin/mongolink resume -``` + ```sh + bin/percona-mongolink resume + ``` #### Using HTTP API -```sh -curl -X POST http://localhost:2242/resume -``` + ```sh + curl -X POST http://localhost:2242/resume + ``` ### Checking the Status @@ -134,15 +133,15 @@ To check the current status of the replication process, you can either use the c #### Using Command-Line Interface -```sh -bin/mongolink status -``` + ```sh + bin/percona-mongolink status + ``` #### Using HTTP API -```sh -curl http://localhost:2242/status -``` + ```sh + curl http://localhost:2242/status + ``` ## MongoLink Options @@ -157,9 +156,9 @@ When starting the MongoLink server, you can use the following options: Example: -```sh -bin/mongolink --source --target --port 2242 --log-level debug --log-json -``` + ```sh + bin/percona-mongolink --source --target --port 2242 --log-level debug --log-json + ``` ## Log JSON Fields @@ -175,20 +174,20 @@ When using the `--log-json` option, the logs will be output in JSON format with Example: -```json -{ "level": "info", - "s": "clone", - "ns": "db_1.coll_1", - "elapsed_secs": 0, - "time": "2025-02-23 11:26:03.758", - "message": "Cloned db_1.coll_1" } - -{ "level": "info", - "s": "mongolink", - "elapsed_secs": 0, - "time": "2025-02-23 11:26:03.857", - "message": "Change replication stopped at 1740335163.1740335163 source cluster time" } -``` + ```json + { "level": "info", + "s": "clone", + "ns": "db_1.coll_1", + "elapsed_secs": 0, + "time": "2025-02-23 11:26:03.758", + "message": "Cloned db_1.coll_1" } + + { "level": "info", + "s": "mongolink", + "elapsed_secs": 0, + "time": "2025-02-23 11:26:03.857", + "message": "Change replication stopped at 1740335163.1740335163 source cluster time" } + ``` ## HTTP API @@ -203,12 +202,12 @@ Starts the replication process. Example: -```json -{ - "includeNamespaces": ["dbName.*", "anotherDB.collName1", "anotherDB.collName2"], - "excludeNamespaces": ["dbName.collName"] -} -``` + ```json + { + "includeNamespaces": ["dbName.*", "anotherDB.collName1", "anotherDB.collName2"], + "excludeNamespaces": ["dbName.collName"] + } + ``` #### Response @@ -217,11 +216,11 @@ Example: Example: -```json -{ - "ok": true -} -``` + ```json + { + "ok": true + } + ``` ### POST /finalize @@ -234,11 +233,11 @@ Finalizes the replication process. Example: -```json -{ - "ok": true -} -``` + ```json + { + "ok": true + } + ``` ### POST /pause @@ -251,11 +250,11 @@ Pauses the replication process. Example: -```json -{ - "ok": true -} -``` + ```json + { + "ok": true + } + ``` ### POST /resume @@ -268,11 +267,11 @@ Resumes the replication process. Example: -```json -{ - "ok": true -} -``` + ```json + { + "ok": true + } + ``` ### GET /status @@ -298,26 +297,26 @@ The /status endpoint provides the current state of the MongoLink replication pro Example: -```json -{ - "ok": true, - "state": "running", - "info": "Initial Sync", - - "lagTime": 22, - "eventsProcessed": 5000, - "lastReplicatedOpTime": "1740335200.5", - - "initialSync": { - "completed": false, - "lagTime": 5, - - "cloneCompleted": false, - "estimatedCloneSize": 5000000000, - "clonedSize": 2500000000 - } -} -``` + ```json + { + "ok": true, + "state": "running", + "info": "Initial Sync", + + "lagTime": 22, + "eventsProcessed": 5000, + "lastReplicatedOpTime": "1740335200.5", + + "initialSync": { + "completed": false, + "lagTime": 5, + + "cloneCompleted": false, + "estimatedCloneSize": 5000000000, + "clonedSize": 2500000000 + } + } + ``` ## Testing @@ -339,23 +338,23 @@ Example: To run the tests, use the following command: -```sh -poetry run pytest \ - --source-uri \ - --target-uri \ - --mongolink-url http://localhost:2242 \ - --mongolink-bin -``` + ```sh + poetry run pytest \ + --source-uri \ + --target-uri \ + --mongolink-url http://localhost:2242 \ + --mongolink-bin + ``` Alternatively, you can use environment variables: -```sh -export TEST_SOURCE_URI= -export TEST_TARGET_URI= -export TEST_MONGOLINK_URL=http://localhost:2242 -export TEST_MONGOLINK_BIN= -poetry run pytest -``` + ```sh + export TEST_SOURCE_URI= + export TEST_TARGET_URI= + export TEST_MONGOLINK_URL=http://localhost:2242 + export TEST_MONGOLINK_BIN= + poetry run pytest + ``` The `--mongolink-bin` flag or `TEST_MONGOLINK_BIN` environment variable specifies the path to the MongoLink binary. This allows the test suite to manage the MongoLink process, ensuring it starts and stops as needed during the tests. If neither the flag nor the environment variable is provided, you must run MongoLink externally before running the tests. diff --git a/go.sum b/go.sum index 743d64bd..10c3741e 100644 --- a/go.sum +++ b/go.sum @@ -3,24 +3,18 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -46,8 +40,6 @@ go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -66,8 +58,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -76,8 +66,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=