{"id":15068556,"url":"https://github.com/eftec/usagimq","last_synced_at":"2025-04-10T17:41:33.052Z","repository":{"id":56975562,"uuid":"110462216","full_name":"EFTEC/UsagiMQ","owner":"EFTEC","description":"It is a library","archived":false,"fork":false,"pushed_at":"2018-08-06T15:15:08.000Z","size":215,"stargazers_count":11,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T15:21:45.082Z","etag":null,"topics":["message-queue","mq","php7","redis"],"latest_commit_sha":null,"homepage":"https://www.eftec.cl","language":"PHP","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/EFTEC.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}},"created_at":"2017-11-12T19:30:25.000Z","updated_at":"2024-09-23T21:03:37.000Z","dependencies_parsed_at":"2022-08-21T11:50:52.467Z","dependency_job_id":null,"html_url":"https://github.com/EFTEC/UsagiMQ","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FUsagiMQ","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FUsagiMQ/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FUsagiMQ/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FUsagiMQ/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EFTEC","download_url":"https://codeload.github.com/EFTEC/UsagiMQ/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248262187,"owners_count":21074260,"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":["message-queue","mq","php7","redis"],"created_at":"2024-09-25T01:38:04.389Z","updated_at":"2025-04-10T17:41:33.034Z","avatar_url":"https://github.com/EFTEC.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"![logo](visio/logo.png \"logo\")\n\n# UsagiMQ\nA minimalist (less than 500 lines of code) Message Queue by using Redis and PHP in a single box (one class)\n\n\n\n## Why I should use a Message Queue (MQ)?\n\nLet’s say the next example, a system where one system sends information to another, for example a web client and a web service.\n\nIf the webservice is doing a **slow operation and its receiving the information of many clients** at once then, sooner or later, the system could collapses or bottleneck.\n\nFor example, if every client uses 0.1 second to do the operation (receiving the information and storing in the database), and we have 1000 customers then, every operation could take 1.6 minutes.\n\n\n![Web Service](visio/WebService.jpg \"Web Service\")\n\nThe solution is to add a Message Queue to the system. A Message Queue is only a server that stores messages/operations received by a PUBLISHER and later a SUBSCRIBER could execute.\n\nFor the same example, a PUBLISHER (former client) could uses 0.001 to call the MQ. Then the SUBSCRIBER could do all the operations, for example every hour/at night without worry if all the operations take many minutes or hours.\n\n\n\n\n![MQ](visio/MQ.jpg \"MQ\")\n\nThe MQ should be as fast as possible and be able to listen and store the request (envelope) of every publisher. However, the MQ is not doing the end operation, its similar to a email server.\nLater, a subscriber could read this information and process as correspond.\n\nThe drawback of this method is it adds a delay, the process is not executed synchronously but asynchronously, and the PUBLISHER don't know really if the information was processed correctly by the SUBSCRIBER.\n\n## Considerations\n\nThis library uses Redis. Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.\n\n## Why UsagiMQ?\n\nWhile there are many Message Queue in the market (including open source / freeware / commercial) but most of them are heavyweight.\nUsagiMQ is lightweight, it was developed thinking in customization. You could optimize and customize it for your needing, for example, changing the structure of envelope.  \n\nIt is a software based solution that could be **re-programmed** as you want to. Instead, most MQ are **configured-based**.\n\nFor example, you could create easily a ORCHESTATION, CHOREOGRAPHY or A CLUSTER via software.\n\nUsagiMQ lightweight:\n\n- One class, it requires Redis and nothing more.\n- \u003c 500 lines of code.\n- Easy customization.\n- **It requires a single file (UsagiMQ.php)** \n\n## Is it scalable?\n\nYes, but it requires a LOAD BALANCER that you could program or use a software or hardware solution. Its your call.\n\n## Envelope structure\n\n- id = the identified of the envelope (required).  \n- from = who send the envelope (optional)  \n- body = the content of the envelope (required).  \n- date = date when it was received. (required, generated)  \n- try = number of tries. (required, for use future, generated)  \n\n\n## MQ Server\n\nWho is listening and storing the envelope (request). It should be as fast as possible.\n\nExample:\n```\ninclude \"UsagiMQ.php\";\n$usa=new UsagiMQ(\"127.0.0.1\",6379,1);\nif ($usa-\u003econnected) {\n    $info=$usa-\u003ereceive();\n    if ($info=='NO INFO') {\n        $usa-\u003ewebUI(); // if not information is send, then it opens the UI.  It is optional\n    } else {\n        echo $info; // show the result.\n    }\n} else {\necho \"not connected\";\n}\n```\n\nExample MQ server that calls a worker (subscriber).  See example : mqwithworker.php\n\n\n### Publisher (who sends the request/envelope)\n\nA publisher requires to send a POST to the page. So it could be a CURL, JavaScript, PHP, Java, C# and many more.\n\nThe url should be as follow:\nmq.php?id=**ID**\u0026op=**OP**\u0026from=**FROM**\n\nwhile the body (content) should be sends as POST.\n\n- ID = is an identified of the message (required but not specifically should be unique)\n- OP = the operation to do. Its some sort of folder or category.\n- FROM = who is sending the message.   It could be used for authentication.\n\n\n```\n\u003c?php\n$ch = curl_init();\n\ncurl_setopt($ch, CURLOPT_URL,            \"http://localhost/UsagiMQ/mq.php?id=200\u0026op=INSERTCUSTOMER\u0026from=SALESSYSTEM\" );\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );\ncurl_setopt($ch, CURLOPT_POST,           1 );\ncurl_setopt($ch, CURLOPT_POSTFIELDS,     \"** IT IS WHAT WE WANT TO SEND**\" );\ncurl_setopt($ch, CURLOPT_HTTPHEADER,     array('Content-Type: text/plain'));\n\n$result=curl_exec ($ch);\n\necho $result; // if returns OKI then the operation was successful. Otherwise, it an error.\n```\n\n\n## Subscriber (local)\n\nIt’s a local subscriber (has access to Redis). However, it could be used for to create a remote subscriber.\n\nMay be it could runs as a daemon / in a schedule task / or at request.\n\nExample\n```\n\u003c?php\n// its a local subscriber\ninclude \"UsagiMQ.php\";\n\n$usa=new UsagiMQ(\"127.0.0.1\",6379,1);\nif (!$usa-\u003econnected) {\n    echo \"not connected\";\n    die(1);\n}\n\n$listEnveloper=$usa-\u003elistPending(\"insert\");\n\nforeach($listEnveloper as $id) {\n    $env=$usa-\u003ereadItem($id);\n    var_dump($env);\n    // todo: code goes here\n\n    // $correct indicates if the operation was successful or not. For example, if the operation was to insert and the operation failed.\n    // We also could decide to delete it for any case. Its up to us.\n    if ($correct) {\n        $usa-\u003edeleteItem($id); // YAY!\n    } else {\n        $usa-\u003efailedItem($id,$env); // booh hiss!.\n    }\n}\n```\n\n# Commands\n\n## Constructor\n\n\u003e $usa=new UsagiMQ($IPREDIS,$PORT,$DATABASE);\n\n$IPREDIS indicates the IP of where is the Redis server.\n$PORT (optional) indicates the REDIS port (default value 6379)\n$DATABASE (optional), indicates the database of Redis (0 is the default value)\n## receive()\n\nReceive information from the PUBLISHER.\n\n## listPending($op)\n\nList all keys of pending envelopers per operation.  \n\nexample:\n\n\u003e $array=$usa-\u003elistPending('insert');\n\n\u003e $array=$usa-\u003elistPending('update');\n\n\n## readItem($key)\n\nRead an item. When an item is read, its not deleted. It should be deleted once its processed.\nThe key could be obtained by the command listPending.\n\nExample:\n\u003e $usa-\u003ereadItem('UsagiMQ_insert:2');\n\n\n## deleteItem($key)\n\nDelete an item.   \nThe key could be obtained by the command listPending.  \nExample:\n\u003e $usa-\u003edeleteItem('UsagiMQ_insert:2');\n\n## failedItem($key,$arr)\n\nWe mark the item as failed. A failed item, is a item that we will try it again (until a limit). If we failed in all tries then, we will delete the item.   \n- The key could be obtained by the command listPending.\n- $arr is the array with the envelope [id,from,body,date,try]   \nExample:\n\u003e $usa-\u003efailedItem('UsagiMQ_insert:2',array('id'=\u003e2,'from'=\u003e'system','body'=\u003e'xxx','date'=\u003e'2000-01-01','try'=\u003e0));\n\n\n## deleteAll()\n\nDelete all items and resets the counter. \n\n## close()\n\nClose Redis. Its not required to use.\n\n## showUI()\n\nOptional. It shows an UI with statistics. The default user and password is **admin** and you should change it.\n\n![logo](visio/uitable.jpg \"uitable\")\n\n# versions\n\n- 2017-11-12 1.0 first version\n- 2017-11-14 1.1 add new members and fixed the operation listPending. Now, its sorted.\n- 2017-11-19 1.2 add UI\n- 2017-11-21 1.3 add new functionalities for the UI. The code is still lower than 500 lines of code.\n- 2018-08-06 1.4 some fixes\n\n## Todo\n\n- Error control / Log\n- Readme missing the command\n- Readme missing the PUBLISHER.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fusagimq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feftec%2Fusagimq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fusagimq/lists"}