{"id":18740577,"url":"https://github.com/aratz-lasa/globalcounter","last_synced_at":"2025-11-20T00:30:17.671Z","repository":{"id":101999925,"uuid":"176168422","full_name":"aratz-lasa/globalCounter","owner":"aratz-lasa","description":"Global counter for achieving complete order in distributed systems ","archived":false,"fork":false,"pushed_at":"2020-03-03T18:54:47.000Z","size":25,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-28T18:54:52.858Z","etag":null,"topics":["complete-order","counter","distributed","distributed-systems","distributed-tracing","global","python","server","trio"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aratz-lasa.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":"2019-03-17T22:27:59.000Z","updated_at":"2024-08-28T21:30:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"bed13a0c-70d0-4353-be82-762d8a3f30e7","html_url":"https://github.com/aratz-lasa/globalCounter","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/aratz-lasa%2FglobalCounter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aratz-lasa%2FglobalCounter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aratz-lasa%2FglobalCounter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aratz-lasa%2FglobalCounter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aratz-lasa","download_url":"https://codeload.github.com/aratz-lasa/globalCounter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239619573,"owners_count":19669447,"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":["complete-order","counter","distributed","distributed-systems","distributed-tracing","global","python","server","trio"],"created_at":"2024-11-07T15:39:47.017Z","updated_at":"2025-11-20T00:30:17.590Z","avatar_url":"https://github.com/aratz-lasa.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# globalCounter\nHave you ever wanted to achieve **complete order** in a distributed system? **GlobalCounter** is a simple solution. It is a server that works as a **global counter**. This gives you an easy way to locally timestamp functions.\n\n# Description\n## Basic Concepts\n- **Counter**: It is a program that *counts*. It contains a *dict* of *Topic*-\u003e*Sum*. *To count* means adding 1 to a topic's sum. \n- **Topic**: It is a string representing a sum. Its main usage is for having logically several *count*s at the same time.\n- **Sum**: It is a topic's count. *Count* and *Sum* are synonyms.\n\n## Asynchronous vs Multiprocess\nGlobalCounter supports **asynchronous** and **multiprocessing** Client and Server. \n\nIt uses [Trio](https://github.com/python-trio/trio) for asynchronous programming. The server spawns one coroutine for every request.\n\nFor multiprocessing, the Server contains a Pool of processes. The maximum amount of Processes in the Pool, it is specified when initializing the Server Class. By default it is equal to system's cpu amount.\n\n```python\nfrom multiprocessing import Pool, Queue, Manager, cpu_count\n...\nMAX_WORKERS = cpu_count()\n...\ndef __init__(self, ip=\"0.0.0.0\", port=0, max_workers=MAX_WORKERS):\n    ...\n\n```\n\n\n## Transport layer\nIt supports both **TCP** and **UDP** Client and Server connections.\n\n## Methods\n|Method|Description|\n|---|----|\n|COUNT|Adds 1 to *{topic}*, and returns the value|\n|RESET|Sets *{topic}* to 0|\n\n## Protocol\nA message is formatted: \n- 1st byte: **OP_CODE**\n- Remaining bytes: **Data**\n \n\n|Method|OP_CODE|Data|\n|---|---|---|\n|COUNT|0|*{topic}*:utf-8 str|\n|COUNT response|128|*{sum}*:unsigned number|\n|RESET|1|*{topic}*:utf-8 str|\n|RESET response|129|_|\n\n# Usage\n\n## Server\n#### UDP Server\n```python\nfrom globalCounter.server.counter_server import UDPCounterServer\n\n\nglobal_counter = UDPCounterServer(ip=\"127.0.0.1\", port=9999, max_workers=4)\nglobal_counter.run()\n```\n\n#### TCP Server\n```python\nfrom globalCounter.server.counter_server import TCPCounterServer\n\n\nglobal_counter = TCPCounterServer(ip=\"127.0.0.1\", port=9999, max_workers=4)\nglobal_counter.run()\n```\n\n#### Async UDP Server\n```python\nimport trio\n\nfrom globalCounter.server.async_counter_server import AsyncUDPCounterServer\n\n\nasync def run_global_counter(global_counter):\n    await global_counter.run()\n\nglobal_counter = AsyncUDPCounterServer(ip=\"127.0.0.1\", port=9999)\ntrio.run(run_global_counter, global_counter)\n```\n\n#### Async TCP Server\n```python\nimport trio\n\nfrom globalCounter.server.async_counter_server import AsyncTCPCounterServer\n\n\nasync def run_global_counter(global_counter):\n    await global_counter.run()\n\nglobal_counter = AsyncTCPCounterServer(ip=\"127.0.0.1\", port=9999)\ntrio.run(run_global_counter, global_counter)\n```\n\n## Client\n#### UDP client\n```python\nfrom globalCounter.client.counter_client import count, reset\n\n\ncount_num = count(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\n\nreset(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\n\n```\nUsing decorators:\n```python\nfrom globalCounter.client.counter_client import count_deco\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\ndef do_something():\n    return \"Something\"\n\n\ncount_num, something = do_something()\n```\n#### TCP client\n```python\nfrom globalCounter.client.counter_client import count, reset\n\ncount_num = count(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\n\nreset(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\n\n```\nUsing decorators:\n```python\nfrom globalCounter.client.counter_client import count_deco\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\ndef do_something():\n    return \"Something\"\n\n\ncount_num, something = do_something()\n```\n#### Async UDP client\n```python\nimport trio\n\nfrom globalCounter.client.async_counter_client import count, reset\n\nasync def run_count_and_reset():\n    count_num = await count(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\n    \n    await reset(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\n\n\ntrio.run(run_count_and_reset)\n\n```\nUsing decorators:\n```python\nimport trio\nfrom globalCounter.client.async_counter_client import count_deco\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\ndef do_something():\n    return \"Something\"\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999)\nasync def do_something_async():\n    return \"Something\"\n\n\ncount_num, something = trio.run(do_something)\n\ncount_num, something = trio.run(do_something_async)\n```\n#### Async TCP client\n```python\nimport trio\n\nfrom globalCounter.client.async_counter_client import count, reset\n\nasync def run_count_and_reset():\n    count_num = await count(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\n    \n    await reset(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\n\n\ntrio.run(run_count_and_reset)\n\n```\nUsing decorators:\n```python\nimport trio\nfrom globalCounter.client.async_counter_client import count_deco\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\ndef do_something():\n    return \"Something\"\n\n\n@count_deco(topic=\"topic\", ip=\"127.0.0.1\", port=9999, tcp=True)\nasync def do_something_async():\n    return \"Something\"\n\n\ncount_num, something = trio.run(do_something)\n\ncount_num, something = trio.run(do_something_async)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faratz-lasa%2Fglobalcounter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faratz-lasa%2Fglobalcounter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faratz-lasa%2Fglobalcounter/lists"}