{"id":20883924,"url":"https://github.com/owner-maker/nats-learning","last_synced_at":"2026-04-12T18:14:34.443Z","repository":{"id":65331863,"uuid":"583909840","full_name":"Owner-maker/nats-learning","owner":"Owner-maker","description":"Provides you a REST API to work with user orders models. Main service is a subscriber to the Nats, gets Orders from it, stores in DB and cache, provides REST API to get them. Also there is a publisher which sends the json Order to the Nats.","archived":false,"fork":false,"pushed_at":"2023-02-08T11:41:53.000Z","size":216,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-19T10:41:56.183Z","etag":null,"topics":["api-rest","docker","docker-compose","gin","golang","gorm","makefile","nats-streaming","postgres","rest","swagger","vegeta","wrk"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Owner-maker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-31T12:20:34.000Z","updated_at":"2023-05-24T10:01:39.000Z","dependencies_parsed_at":"2023-02-12T21:30:38.996Z","dependency_job_id":null,"html_url":"https://github.com/Owner-maker/nats-learning","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Owner-maker%2Fnats-learning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Owner-maker%2Fnats-learning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Owner-maker%2Fnats-learning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Owner-maker%2Fnats-learning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Owner-maker","download_url":"https://codeload.github.com/Owner-maker/nats-learning/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243266964,"owners_count":20263798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","docker","docker-compose","gin","golang","gorm","makefile","nats-streaming","postgres","rest","swagger","vegeta","wrk"],"created_at":"2024-11-18T08:08:24.035Z","updated_at":"2025-12-11T18:36:37.422Z","avatar_url":"https://github.com/Owner-maker.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nats-learning\nThis repo is for the purpose of studying nats streaming in Go.\n\n## Task\n\nLook file: task.pdf\n\n## Start instructions\n\n1. Clone the repository locally to any directory on your device \\\n   ``` git clone https://github.com/Owner-maker/nats-learning.git```\n2. Change to the project directory manually or using the console \\\n   ```cd nats-learning```\n3. Build \u0026 run docker containers ```docker-compose build \u0026\u0026 docker-compose up``` \u003cbr\u003e OR using a Make utility ```make docker```\n4. After starting the containers, all entities will be automatically created in the database using a gorm auto migration\n5. After the container is launched, the Swagger html page will also be available for the convenience of API testing \\\n   ```http://localhost:8080/swagger/index.html#/```\n\n**To add** a new Order entity, you must, if desired, ```make changes to the ./internal/web/model.json``` file and then build \u0026 run special Go script \u003cbr\u003e```go run github.com/Owner-maker/nats-learning/cmd/publisher```\n   OR using a Make utility ```make pub```\n\n### Technologies:\n- Golang\n- Gin\n- Gorm\n- PostgreSQL\n- Swagger\n- Docker\n- Nats streaming\n- WRK\n- Vegeta\n\n### \u003ca name=\"up\"\u003e\u003c/a\u003eHTTP methods:\n\n- [Get the order from the database](#getdbOrder)\n- [Get the order from the cache](#getorder)\n- [Get all orders from the cache](#getorders)\n\n## Request examples:\n\n### \u003ca name=\"getdborder\"\u003eGet the order from the database\u003c/a\u003e - method GET\n```http://localhost:8080/api/order/db/:uid``` \n\nFor example input path parameter - uid -\u003e ```b563feb7b2b84b6teST``` \u003cbr\u003e\nOutput  \n```\n{\n  \"order_uid\": \"b563feb7b2b84b6teST\",\n  \"track_number\": \"WBILMTESTTRACK\",\n  \"entry\": \"WBIL\",\n  \"locale\": \"en\",\n  \"internal_signature\": \"\",\n  \"customer_id\": \"test\",\n  \"delivery_service\": \"meest\",\n  \"shardkey\": \"9\",\n  \"sm_id\": 99,\n  \"date_created\": \"2021-11-26T06:22:19Z\",\n  \"oof_shard\": \"1\",\n  \"delivery\": {\n    \"name\": \"Test Testov\",\n    \"phone\": \"+9720000000\",\n    \"zip\": \"2639809\",\n    \"city\": \"Kiryat Mozkin\",\n    \"address\": \"Ploshad Mira 15\",\n    \"region\": \"Kraiot\",\n    \"email\": \"test@gmail.com\"\n  },\n  \"payment\": {\n    \"transaction\": \"b563feb7b2b84b6test\",\n    \"request_id\": \"\",\n    \"currency\": \"USD\",\n    \"provider\": \"wbpay\",\n    \"amount\": 1817,\n    \"payment_dt\": 1637907727,\n    \"bank\": \"alpha\",\n    \"delivery_cost\": 1500,\n    \"goods_total\": 317,\n    \"custom_fee\": 0\n  },\n  \"items\": [\n    {\n      \"chrt_id\": 9934930,\n      \"track_number\": \"WBILMTESTTRACK\",\n      \"price\": 453,\n      \"rid\": \"ab4219087a764ae0btest\",\n      \"name\": \"Mascaras\",\n      \"sale\": 30,\n      \"size\": \"0\",\n      \"total_price\": 317,\n      \"nm_id\": 2389212,\n      \"brand\": \"Vivienne Sabo\",\n      \"status\": 202\n    }\n  ]\n}\n```\n\n### \u003ca name=\"getorder\"\u003eGet the order from the cache\u003c/a\u003e - method GET\n```http://localhost:8080/api/order/:uid``` \\\nInput parameter uid \\\nOutput same as from the method ```Get the order from the database```\n\n### \u003ca name=\"getorders\"\u003eGet all orders from the cache\u003c/a\u003e - method GET\n[go to all methods](#up) \\\n```http://localhost:8080/api/orders``` \n\nOutput\n\n```\n{\n  \"data\": [\n    {\n      \"order_uid\": \"b563feb7b2b84b6teST\",\n      \"track_number\": \"WBILMTESTTRACK\",\n      \"entry\": \"WBIL\",\n      \"locale\": \"en\",\n      \"internal_signature\": \"\",\n      \"customer_id\": \"test\",\n      \"delivery_service\": \"meest\",\n      \"shardkey\": \"9\",\n      \"sm_id\": 99,\n      \"date_created\": \"2021-11-26T06:22:19Z\",\n      \"oof_shard\": \"1\",\n      \"delivery\": {\n        \"name\": \"Test Testov\",\n        \"phone\": \"+9720000000\",\n        \"zip\": \"2639809\",\n        \"city\": \"Kiryat Mozkin\",\n        \"address\": \"Ploshad Mira 15\",\n        \"region\": \"Kraiot\",\n        \"email\": \"test@gmail.com\"\n      },\n      \"payment\": {\n        \"transaction\": \"b563feb7b2b84b6test\",\n        \"request_id\": \"\",\n        \"currency\": \"USD\",\n        \"provider\": \"wbpay\",\n        \"amount\": 1817,\n        \"payment_dt\": 1637907727,\n        \"bank\": \"alpha\",\n        \"delivery_cost\": 1500,\n        \"goods_total\": 317,\n        \"custom_fee\": 0\n      },\n      \"items\": [\n        {\n          \"chrt_id\": 9934930,\n          \"track_number\": \"WBILMTESTTRACK\",\n          \"price\": 453,\n          \"rid\": \"ab4219087a764ae0btest\",\n          \"name\": \"Mascaras\",\n          \"sale\": 30,\n          \"size\": \"0\",\n          \"total_price\": 317,\n          \"nm_id\": 2389212,\n          \"brand\": \"Vivienne Sabo\",\n          \"status\": 202\n        }\n      ]\n    }\n  ]\n}\n```\n\n### Errors\n\nIn case for example where there is not such order in DB respond is the error information\n\nFor example, status code is  ```500```\n\n```\n{\n  \"message\": \"record not found\"\n}\n```\n\n## Stress tests\n### WRK \n#### Testing method ```api/order/db/:uid``` \u003cbr\u003e (from the Postgres DB)\n\n```\n40 goroutine(s) running concurrently\n1030 requests in 5.062448285s, 947.52KB read\nRequests/sec:           203.46\nTransfer/sec:           187.17KB\nAvg Req Time:           196.599933ms\nFastest Request:        21.3168ms\nSlowest Request:        600.2796ms\nNumber of Errors:       0\n```\n\n#### Testing method ```api/order/:uid``` \u003cbr\u003e (from the app's cache)\n\n```\n40 goroutine(s) running concurrently\n12158 requests in 4.98550031s, 10.92MB read\nRequests/sec:           2438.67\nTransfer/sec:           2.19MB\nAvg Req Time:           16.402369ms\nFastest Request:        2.9976ms\nSlowest Request:        136.518ms\nNumber of Errors:       0\n```\n\n### Vegeta\n#### Testing method ```api/order/db/:uid``` \u003cbr\u003e (from the Postgres DB)\n\n```\necho \"GET http://localhost:8080/api/order/db/b563feb7b2b84b6teST\" | vegeta attack -duration=5s -rate=200/s --output results.bin | vegeta report results.bin\nRequests      [total, rate, throughput]  1000, 200.68, 199.27\nDuration      [total, attack, wait]      5.0182288s, 4.982991s, 35.2378ms\nLatencies     [mean, 50, 95, 99, max]    68.966785ms, 62.60285ms, 146.067349ms, 195.7005ms, 325.7584ms\nBytes In      [total, mean]              835000, 835.00\nBytes Out     [total, mean]              0, 0.00\nSuccess       [ratio]                    100.00%\nStatus Codes  [code:count]               200:1000\n```\n\n#### Testing method ```api/order/:uid``` \u003cbr\u003e (from the app's cache)\n\n```\necho \"GET http://localhost:8080/api/order/b563feb7b2b84b6teST\" | vegeta attack -duration=5s -rate=200/s --output results.bin | vegeta report results.bin\nRequests      [total, rate, throughput]  997, 199.56, 199.41\nDuration      [total, attack, wait]      4.9997579s, 4.995879s, 3.8789ms\nLatencies     [mean, 50, 95, 99, max]    3.691205ms, 3.653355ms, 4.527508ms, 5.15411ms, 15.5271ms\nBytes In      [total, mean]              832495, 835.00\nBytes Out     [total, mean]              0, 0.00\nSuccess       [ratio]                    100.00%\nStatus Codes  [code:count]               200:997\n```\n\n### What would I improve?\n\n1) Do not use an interface{} as a field value of map (inner app's cache) -\u003e problem is in a manual casting type interface{} to the specific value, very resource intensive\n2) Do not use inner Go automigration of tables into the DB, use a stored procedures instead -\u003e for more detailed settings\n3) Make more unit test","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowner-maker%2Fnats-learning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fowner-maker%2Fnats-learning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowner-maker%2Fnats-learning/lists"}