{"id":19275723,"url":"https://github.com/trycontrolmymind/adventure-works","last_synced_at":"2026-02-08T20:33:22.449Z","repository":{"id":144078786,"uuid":"144066347","full_name":"trycontrolmymind/adventure-works","owner":"trycontrolmymind","description":"Test work for MalwareBytes company","archived":false,"fork":false,"pushed_at":"2018-09-03T15:05:51.000Z","size":42287,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-10T10:31:12.852Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trycontrolmymind.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2018-08-08T20:52:31.000Z","updated_at":"2018-09-03T15:05:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"e2d08de3-26c4-4b24-b368-6a9b60472311","html_url":"https://github.com/trycontrolmymind/adventure-works","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/trycontrolmymind/adventure-works","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trycontrolmymind%2Fadventure-works","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trycontrolmymind%2Fadventure-works/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trycontrolmymind%2Fadventure-works/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trycontrolmymind%2Fadventure-works/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trycontrolmymind","download_url":"https://codeload.github.com/trycontrolmymind/adventure-works/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trycontrolmymind%2Fadventure-works/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29242878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T19:36:48.828Z","status":"ssl_error","status_checked_at":"2026-02-08T19:27:12.336Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-11-09T20:51:45.335Z","updated_at":"2026-02-08T20:33:22.430Z","avatar_url":"https://github.com/trycontrolmymind.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"- [Installation](#installation)\n- [1. Choose a technology stack](#1-choose-a-technology-stack)\n- [2. Make a simple HTTP service](#2-make-a-simple-http-service)\n- [3. Make a worker for reviews](#3-make-a-worker-for-reviews)\n- [4. Make a worker for review notification](#4-make-a-worker-for-review-notification)\n- [My notes](#my-notes)\n- [DB changes](#db-changes)\n- [Simple API tests](#simple-api-tests)\n  - [LoadTest](#loadtest)\n\n# Installation\n```bash\ngit clone https://github.com/trycontrolmymind/adventure-works.git\ncd adventure-works\ndocker-compose up --build\n```\nWhat's outside of container:\n- http://0.0.0.0:8888 - API\n- http://0.0.0.0:8080 - PostgreSQL mini admin panel\n- http://0.0.0.0:6379 - Redis\n\n# 1. Choose a technology stack\n- API Layer\n  - Node.js - Workers language\n  - Express.js - Request router\n  - body-parser - Json parser middleware\n  - Joi - validate incoming requests\n  - Winston - logging things\n  - BusMQ - queue manager\n  - Fetch - request simplify\n  - Mocha, Chai - testing\n  - Node-postgres - driver for PostgreSQL\n- DB Layer - PostgreSQL\n- Queue Layer - Redis\n\n# 2. Make a simple HTTP service\n•\tAPI Layer (HTTP):\n\n-\tClient submits a product review via HTTP:\n\n```bash\ncurl -X POST http://0.0.0.0:8888/api/reviews \\\n \t-H 'Content-Type: application/json' \\\n  -d '{\n      \"name\": \"Elvis Presley\",\n      \"email\": \"theking@elvismansion.com\",\n      \"productid\": \"8\",\n      \"review\": \"I really love the product and will recommend!\"\n  }'\n```\n-\tAPI HTTP response:\n```\n{\n\t\"success\": true,\n\t\"reviewID\": [id integer]\n}\n```\nThe API puts the product review into the database and onto a queue for processing.\n- Create some simple tests;\n- Write review to DB;\n\n# 3. Make a worker for reviews\n- Validate incoming message;\n- Check for a bad words;\n- Change status of current review;\n- Send review to Notification worker;\n\n# 4. Make a worker for review notification\n- Validate incoming message;\n- Emulate notification;\n\n# My notes\n- Better to create a simple .sql or .sql.gz file for DB example, like in my repository;\n- No concrete description of how review will change status.\n- Strange description about when reviewer should be 'notified'\n```\npost the review live once approved or archive if not approved and notify the reviewer via email (simulated) once the review status has been finalized.\n```\nand other one is...\n```\nOnce the review is approved and published, the reviewer is notified via email.\n```\n\n# DB changes\n- Update PK counter of product.review\n- Create product.reviewstatus table\n- Update product.review, adding reviewstatusid from product.reviewstatus\n\n# Simple API tests\n```bash\nnpm run test\n```\n\n```\nAPI Node.js\n  ✓ should return 404 if unexisted path\n  ✓ should not have X-Powered-By header\n  ✓ should return 400 if json is invalid\n  ✓ should return 200 if ok body\n  ✓ should return success false if productid not exists\n\n\n5 passing (74ms)\n```\n\n## LoadTest\n```\nMac middle 15\nCPU: 6 (2,2 GHz Intel Core i7)\nMemory: 6 GB\n```\n```json\n{\n  \"totalRequests\": 10000,\n  \"totalErrors\": 0,\n  \"totalTimeSeconds\": 103.874700704,\n  \"rps\": 96,\n  \"meanLatencyMs\": 10.3,\n  \"maxLatencyMs\": 749,\n  \"minLatencyMs\": 5,\n  \"percentiles\": {\n    \"50\": 9,\n    \"90\": 13,\n    \"95\": 16,\n    \"99\": 24\n  },\n  \"errorCodes\": {}\n}\n```\n\nLoadTest using remote machine:\n- CPU: 1vCPU 2Ghz\n- Memory: 1GB\n\n```json\n{\n  \"totalRequests\": 1808,\n  \"totalErrors\": 0,\n  \"totalTimeSeconds\": 148.748090427,\n  \"rps\": 12,\n  \"meanLatencyMs\": 82.2,\n  \"maxLatencyMs\": 1087,\n  \"minLatencyMs\": 73,\n  \"percentiles\": {\n    \"50\": 78,\n    \"90\": 87,\n    \"95\": 90,\n    \"99\": 123\n  },\n  \"errorCodes\": {}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrycontrolmymind%2Fadventure-works","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrycontrolmymind%2Fadventure-works","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrycontrolmymind%2Fadventure-works/lists"}