{"id":27900564,"url":"https://github.com/eftec/multione","last_synced_at":"2026-02-05T06:01:07.562Z","repository":{"id":269992422,"uuid":"908169361","full_name":"EFTEC/MultiOne","owner":"EFTEC","description":"MultiOne is a library to execute concurrent tasks programmed in PHP using JavaScript","archived":false,"fork":false,"pushed_at":"2025-01-04T15:08:47.000Z","size":154,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-13T08:26:20.416Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","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/EFTEC.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,"zenodo":null}},"created_at":"2024-12-25T10:30:57.000Z","updated_at":"2025-01-10T17:00:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"9afc1b54-848a-4619-b960-e17cb430ed77","html_url":"https://github.com/EFTEC/MultiOne","commit_stats":null,"previous_names":["eftec/multione"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/EFTEC/MultiOne","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMultiOne","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMultiOne/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMultiOne/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMultiOne/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EFTEC","download_url":"https://codeload.github.com/EFTEC/MultiOne/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMultiOne/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29114494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: 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":"2025-05-05T20:17:19.612Z","updated_at":"2026-02-05T06:01:07.556Z","avatar_url":"https://github.com/EFTEC.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MultiOne\nMultiOne is a library to execute concurrent tasks programmed in PHP using JavaScript.\n\nThis library is focused to run local task easily and without much extra boilerplate.\n\nThe goal is to be able to run CPU intensive tasks using multiples cores by distributing every task in different workers (what does the job).\nIt also adds a new functionality, it allows to simulate a Command Line Interface (CLI) using the web.\n\n[![Packagist](https://img.shields.io/packagist/v/eftec/MultiOne.svg)](https://packagist.org/packages/eftec/MultiOne)\n[![Total Downloads](https://poser.pugx.org/eftec/MultiOne/downloads)](https://packagist.org/packages/eftec/MultiOne)\n[![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)]()\n[![composer](https://img.shields.io/badge/composer-%3E2.0-blue.svg)]()\n[![php](https://img.shields.io/badge/php-7.4-green.svg)]()\n[![php](https://img.shields.io/badge/php-8.4-green.svg)]()\n\n![docs/img5.png](docs/img5.png)\n\n\u003c!-- TOC --\u003e\n* [MultiOne](#multione)\n  * [How to use it?](#how-to-use-it)\n  * [Logic](#logic)\n  * [How to synchronize and share information between every worker?](#how-to-synchronize-and-share-information-between-every-worker)\n  * [Command Line Interface (CLI)](#command-line-interface-cli)\n    * [Example](#example)\n  * [Example of multi operations](#example-of-multi-operations)\n  * [Changelog](#changelog)\n\u003c!-- TOC --\u003e\n\n## How to use it?\nInstall this library using Composer\n```\ncomposer require eftec/multione\n```\n\nAnd call it as follows:\n\n```php\nuse Eftec\\MultiOne\\MultiOne;\ninclude __DIR__ . '/../vendor/autoload.php';\n$multiOne = MultiOne::Factory(\n    1000, // every miliseconds\n    basename(__FILE__), // the url to call\n    4 // the number of workers\n)-\u003esetMethod(\n    static function($numWorkers):array { // the initial call\n        // todo code\n        $result=[];\n        for($instance=0; $instance\u003c$numWorkers; $instance++) {\n            $result[$instance]='initial';\n        }\n        return $result;\n    },\n    static function($idWorker, $body):array { // the worker call                \n        // some job here\n        if($done){\n            return ['type'=\u003e'end','result'=\u003e'done','ui'=\u003e'done'];\n        }       \n        return ['result'=\u003e'working', 'ui'=\u003e\"Worker: $idWorker\"];\n    },\n    static function($bodies) { // the worker-end call\n        echo \"all workers ended\";\n    }\n)-\u003esetHtmls(\n    '\u003cdiv id=\"PREFIX_contentcontent\"\u003e%s\u003c/div\u003e', // how the content is draw\n    '\u003cdiv id=\"PREFIX_worker_%s\"\u003e\u003c/div\u003e\u003cdiv id=\"PREFIX_worker_error_%s\"\u003e\u003c/div\u003e', // how every worker is draw\n    '\u003cdiv id=\"PREFIX_worker_end\"\u003e\u003c/div\u003e', // how the worker-end is draw.\n    \"loading ⏳\" // the loading ui. If empty, then it don't use loading ui\n)-\u003erunAuto();\n```\nThe browser will show the next screen\n![docs/img1.png](docs/img1.png)\n\n\u003e  In the folder examples you can find examples of code.\n\n\n\n## Logic\n\nThere are 3 functions (defined by **setMethod**) that are called in different stages of the process\n\n```php\nsetMethod(\n    static function($numWorkers):array { \n      // the initial call (returns an array with all the payload for each worker)    \n    },\n    static function($idWorker, $body):array { \n      // the worker call                       \n    },\n    static function($bodies) { \n      // the worker-end call, it returns a message.       \n    }\n```\n\n\n* The initial function is called at the beginner of the operation. \n  * It must create the initial payload, it also display the UI and it could show some visual content.\n  * After the initial function is called, then JavaScript (in the HTML) does the rest of operation and coordination.\n* Every \"n\" milliseconds, every worker is called (unless it is in use). Each worker receives the load of its worker.\n  * Once the worker is done, it must return the next structure:\n    * **type** the type of result, example: \"end\" or \"run\". \n      * If a worker returns end, the the worker will stop its operation.\n      * If none is set then it uses \"run\".\n    * **result** the result (load) of the worker. If none is set, then it uses the **ui** (if any) or empty\n    * **ui** the visual result of the worker. If none is set, then it uses **result**\n* When all workers are finished, then worker_end is executed.  \n  * It receives the load of all workers and it results a visual text.\n\n![docs/img2.png](docs/img2.png)\n\n## How to synchronize and share information between every worker?\n\nYou can use the payload to synchronize the operations of every worker.  \n\n![docs/img3.png](docs/img3.png)\n\nHowever, if it is not enough, then you can use the next alternatives: \n\n* You can use an external library such as eftec/cacheone, to share information between workers\n* You can use APCU, Redis, Memcache, database or file system\n* The library contains 3 methods to save file locally\n  * **MultiOne::getGetData** to get some data using a local file\n  * **MultiOne::getSetData** to set some data using a local file\n  * **MultiOne::getSetDataSafe** to get some data, replace the value, and save in a safe way\n\n![docs/img4.png](docs/img4.png)\n\n## Command Line Interface (CLI)\n\nIt is possible to run the library to display a command line interface on web.\n\n![docs/imgcli.png](docs/imgcli.png)\n\nIn CLI mode, the code calls a single worker only when the user inputs a value in the input text.\n\n### Example\n\n```php\nMultiOne::Factory(\n    1000, // every miliseconds\n    basename(__FILE__), // the url to call\n)-\u003esetMethods(\n    static function($numWorkers, $payload): array { // the initial call\n        $_SESSION['USERNAME'] = 'admin';\n        return [\"Start\"], // the initial screen\n];\n    },\n    static function($idWorker, $payload): array { // the worker call\n        // it reads the data and reduces to 1.\n        $username=$_SESSION['USERNAME']??null;\n        if($username===null) {\n            throw new RuntimeException('no user is not set');\n        }\n        return MultiOne::msgRun(\"$username:{$payload['line']}\",\"@$username\u003e \");\n    }\n)\n    -\u003esetCli('\u003e ','100%','600px') // we use a cli\n    -\u003erunAuto();\n```\n\nWhere:\n\n```php\nMultiOne::msgAnswer('run','text to add to the console','a prompt'); // run,full,error\n```\n\n\u003e The text to display could contains colors. Example:\n\n```php\nMultiOne::msgAnswer('run','\u003cred\u003ered text\u003c/red\u003e\u003cbyellow\u003eyellow background\u003c/byellow\u003e');\n```\n\n\n\n## Example of multi operations\n\nYou can find this example in the example folder\n\nLets say we need to execute 100 operations in 4 workers\n\nFirst, we create the 4 workers\n\n```php\nMultiOne::Factory(\n    1000, // every miliseconds\n    basename(__FILE__), // the url to call\n    4     // the number of workers\n)\n```\n\nThen, we create the initial load and we split in 4 workers\n\n```php\nstatic function($numWorkers):array { // the initial call\n    $result=[];\n    $numOper=100;\n    $split=ceil($numOper/$numWorkers);\n    for($instance=0; $instance\u003c$numWorkers; $instance++) {\n        $result[$instance]=['done'=\u003e$split*$instance,'task'=\u003e[\n          'init'=\u003e($split*$instance)+$split,\n          'end'=\u003e$split*$instance]\n          ];\n    }\n    return $result;\n}\n```\n\nThen, every worker must do the job\n\n```php\nstatic function($idWorker, $body):array { // the worker call\n    $body['done'] += 1;\n    if($body['done']\u003e=$body['task']['end']) {\n        $body['done']='ok';\n        return MultiOne::msgAnswer('end',$body,'done');\n    }\n    usleep(random_int(500, 1500));\n    MultiOne::msgAnswer('run',$body,\"Worker: $idWorker\");\n}\n```\n\n// And when all jobs are done, we could close it. It could be used to merge all the results. It only needs to return a visual result.\n\n```php\nstatic function($body) { // the worker-end call\n    echo \"all workers ended\";\n}\n```\n\nOptionally we could do changes in the UI.\n\nFinally, our code could look as follows:\n\n```php\nMultiOne::Factory(\n    1000, // every miliseconds\n    basename(__FILE__), // the url to call\n    4     // the number of workers\n)-\u003esetMethods(\n    static function($numWorkers):array { // the initial call\n        $result=[];\n        $numOper=100;\n        $split=ceil($numOper/$numWorkers);\n        for($instance=0; $instance\u003c$numWorkers; $instance++) {\n          $result[$instance]=['done'=\u003e$split*$instance,'task'=\u003e[\n            'init'=\u003e($split*$instance)+$split,\n            'end'=\u003e$split*$instance]\n            ];\n        }\n        return $result;\n    },\n    static function($idWorker,$body):array { // the worker call\n        $body['done'] += 1;\n        if($body['done']\u003e=$body['task']['end']) {\n            $body['done']='ok';\n            return MultiOne::msgAnswer('end',$body,'done');\n        }\n        usleep(random_int(500, 1500));\n\n        return MultiOne::msgAnswer('run',$body,\"#$idWorker {$body['done']}\");\n    },\n    static function($body) { // the worker-end call\n        echo \"all worker ended\";\n    }\n)-\u003erunAuto();\n```\n\n\n## Changelog\n* 1.3 2025-01-04\n  * Added CLI \n  * Added sessions. By default it uses sessions.\n* 1.2 2025-01-02\n  * Fixed a problem with PHP 8.4 \n* 1.1 2024-12-27\n  * fixed a small bug in initialize some arguments\n  * fixed a bug with some examples.\n* 1.0 2024-12-27\n  * first version \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fmultione","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feftec%2Fmultione","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fmultione/lists"}