{"id":22472983,"url":"https://github.com/truefoundry/async_service","last_synced_at":"2025-03-27T16:25:54.581Z","repository":{"id":187721270,"uuid":"677031618","full_name":"truefoundry/async_service","owner":"truefoundry","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-30T18:16:30.000Z","size":507,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-01T20:12:06.099Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/truefoundry.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-10T15:19:09.000Z","updated_at":"2024-11-29T05:19:40.000Z","dependencies_parsed_at":"2023-08-11T23:10:07.565Z","dependency_job_id":"df85bf34-b15f-4596-b99e-609fd7ed2245","html_url":"https://github.com/truefoundry/async_service","commit_stats":null,"previous_names":["truefoundry/async_service"],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truefoundry%2Fasync_service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truefoundry%2Fasync_service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truefoundry%2Fasync_service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truefoundry%2Fasync_service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/truefoundry","download_url":"https://codeload.github.com/truefoundry/async_service/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245880838,"owners_count":20687614,"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":[],"created_at":"2024-12-06T12:18:19.162Z","updated_at":"2025-03-27T16:25:54.544Z","avatar_url":"https://github.com/truefoundry.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Async Service\n\n## Install\n```console\npip install \"async_processor[sqs]\"\n```\n\n## Quick start\n\n### Write the Processor\n#### `app.py`\n```python\nfrom async_processor import (\n    InputMessageInterface,\n    Processor,\n    WorkerConfig,\n    SQSInputConfig,\n    SQSOutputConfig,\n)\n\n\nclass MultiplicationProcessor(Processor):\n    def process(self, input_message: InputMessageInterface) -\u003e int:\n        body = input_message.get_body()\n        return body[\"x\"] * body[\"y\"]\n\n\napp = MultiplicationProcessor().build_app(\n    worker_config=WorkerConfig(\n        input_config=SQSInputConfig(\n            queue_url=\"YOUR_INPUT_SQS_URL\",\n            visibility_timeout=2,\n        ),\n        output_config=SQSOutputConfig(queue_url=\"YOUR_OUTPUT_SQS_URL\"),\n    ),\n)\n```\n\n### Run the app\n```console\ngunicorn app:app --workers 1 --worker-class uvicorn.workers.UvicornWorker --bind 127.0.0.1:8000\n```\n\nOutput:\n```console\n✦6 ❯ gunicorn app:app --workers 1 --worker-class uvicorn.workers.UvicornWorker --bind 127.0.0.1:8000\n[2023-08-17 16:10:33 +0530] [78736] [INFO] Starting gunicorn 21.2.0\n[2023-08-17 16:10:33 +0530] [78736] [INFO] Listening at: http://127.0.0.1:8000 (78736)\n[2023-08-17 16:10:33 +0530] [78736] [INFO] Using worker: uvicorn.workers.UvicornWorker\n[2023-08-17 16:10:33 +0530] [78738] [INFO] Booting worker with pid: 78738\n[2023-08-17 16:10:33 +0530] [78738] [INFO] Started server process [78738]\n[2023-08-17 16:10:33 +0530] [78738] [INFO] Waiting for application startup.\n2023-08-17 16:10:33,764 - app - INFO - Invoking the processor init method\n2023-08-17 16:10:33,765 - app - INFO - Processor init method execution completed\n2023-08-17 16:10:33,765 - app - INFO - Starting processor runner\n2023-08-17 16:10:34,461 - app - INFO - Started processor runner\n2023-08-17 16:10:34,462 - app - INFO - Polling messages\n[2023-08-17 16:10:34 +0530] [78738] [INFO] Application startup complete.\n```\n\n### Send a synchronus process request\n```console\ncurl 'http://localhost:8000/process' -H 'Content-Type: application/json'  -d '{\"request_id\": \"abc\", \"body\": {\"x\": 1, \"y\": 2}}'\n```\n\nOutput:\n```console\n❯ curl 'http://localhost:8000/process' -H 'Content-Type: application/json'  -d '{\"request_id\": \"abc\", \"body\": {\"x\": 1, \"y\": 2}}'\n{\"request_id\":\"abc\",\"status\":\"SUCCESS\",\"body\":2,\"error\":null}\n```\n\n* A FastAPI documentation dashboard will be available on http://localhost\n\n### Send an asynchronus process request\n#### send_async_request.py\n```python\nimport json\nimport uuid\n\nfrom async_processor import InputMessageV2, OutputMessage, ProcessStatus\nimport boto3\n\n\ndef send_request(input_sqs_url: str, output_sqs_url: str):\n    sqs = boto3.client(\"sqs\")\n    request_id = str(uuid.uuid4())\n\n    sqs.send_message(\n        QueueUrl=input_sqs_url,\n        MessageBody=json.dumps(\n            InputMessageV2(tfy_request_id=request_id, x=1, y=2).dict()\n        ),\n    )\n\n    while True:\n        response = sqs.receive_message(\n            QueueUrl=output_sqs_url, MaxNumberOfMessages=1, WaitTimeSeconds=19\n        )\n        if \"Messages\" not in response:\n            continue\n        msg = response[\"Messages\"][0]\n        response = OutputMessage(**json.loads(msg[\"Body\"]))\n\n        if ProcessStatus[response.status] is not ProcessStatus.SUCCESS:\n            raise Exception(f\"processing failed: {response.error}\")\n        print(response)\n        break\n\nif __name__ == \"__main__\":\n    send_request(input_sqs_url=\"YOUR_INPUT_SQS_URL\", output_sqs_url=\"YOUR_OUTPUT_SQS_URL\")\n```\n\nRun the above python script\n```console\npython send_async_request.py\n```\n\nOutput:\n```console\n❯ python send_async_request.py\nrequest_id='46a4ebc6-afdb-46a0-8587-ba29abf0f0d4' status='SUCCESS' body=2 error=None\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftruefoundry%2Fasync_service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftruefoundry%2Fasync_service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftruefoundry%2Fasync_service/lists"}