{"id":13776220,"url":"https://github.com/slact/ngx_lua_ipc","last_synced_at":"2025-04-14T05:31:34.122Z","repository":{"id":66962031,"uuid":"67723299","full_name":"slact/ngx_lua_ipc","owner":"slact","description":"event-driven interprocess communication for openresty and the nginx lua module","archived":false,"fork":false,"pushed_at":"2019-07-31T06:15:56.000Z","size":166,"stargazers_count":108,"open_issues_count":3,"forks_count":26,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-05-09T23:19:10.141Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slact.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}},"created_at":"2016-09-08T17:02:20.000Z","updated_at":"2024-03-22T09:46:41.000Z","dependencies_parsed_at":"2023-03-22T06:50:09.042Z","dependency_job_id":null,"html_url":"https://github.com/slact/ngx_lua_ipc","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slact%2Fngx_lua_ipc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slact%2Fngx_lua_ipc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slact%2Fngx_lua_ipc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slact%2Fngx_lua_ipc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slact","download_url":"https://codeload.github.com/slact/ngx_lua_ipc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248826593,"owners_count":21167718,"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-08-03T18:00:19.555Z","updated_at":"2025-04-14T05:31:33.716Z","avatar_url":"https://github.com/slact.png","language":"C","readme":"Interprocess communication for lua_nginx_module and openresty. Send named alerts with string data between Nginx worker processes.\n\nAsynchronous, nonblocking, non-locking, and [*fast*](#speed)!\n\n### History \n\nI wrote this as a quick hack to separate the [interprocess code](https://github.com/slact/nchan/tree/master/src/store/memory) out of [Nchan](https://github.com/slact/nchan) mostly on a flight back from [Nginx Conf 2016](https://www.nginx.com/nginxconf/2016). The completion of this module was generously sponsored by [ring.com](https://ring.com). Thanks guys!\n\n# API\n\n```lua\nlocal ipc = require \"ngx.ipc\"\n```\n\n### `ipc.send`\nSend alert to a worker process.\n```lua\nipc.send(destination_worker_pid, alert_name, alert_data)\n```\n\nReturns:\n - `true` on success\n - `nil, error_msg` if `alert_name` length is \u003e 254, `alert_data` length is \u003e 4G, `destination_worker_pid` is not a valid worker process.\n\n\n### `ipc.broadcast`\nBroadcast alert to all workers (including sender).\n```lua\nipc.broadcast(alert_name, alert_data)\n```\n\nReturns:\n - `true` on success\n - `nil, error_msg` if `alert_name` length is \u003e 254 or `alert_data` length is \u003e 4G\n\n### `ipc.receive`\nRegister one or several alert handlers. \nNote that `receive` cannot be used in the `init_by_lua*` context. During startup, use `init_worker_by_lua*`.\n\nRegister an alert handler:\n```lua\nipc.receive(alert_name, function(data)\n  --ipc receiver function for all alerts with string name alert_name\nend)\n```\nReturns:\n - `true`\n\nSeveral alert names can be registered at once by passing a table:\n```lua\nipc.receive({\n  hello = function(data) \n    --got a hello\n  end,\n  goodbye = function(data)\n    --got a goodbye\n  end\n})\n```\n\nDeleting an alert handler:\n```lua\nipc.receive(ipc_alert_name, nil)\n```\n\n*Alerts received without a handler are discarded.*\n\n### `ipc.reply`\nReply to worker that sent an alert. Works only when in an alert receiver handler function.\n\n```lua\n  ipc.receive(\"hello\", function(data)\n    ipc.reply(\"hello-response\", \"hi, you said \"..data)\n  end)\n```\n\nReturns:\n - `true`\n \nRaises error if used outside of a `ipc.receive` handler.\n\n\n### `ipc.sender`\nWhen receiving an alert, `ipc.sender` contains the sending worker\"s process id.\nall other times, it is nil\n```lua\nipc.receive(\"hello\", function(data)\n  if ipc.sender ==  ngx.worker.pid() then\n    --just said hello to myself\n  end\nend)\n```\n\n# Example\n\n`nginx.conf`\n```lua\nhttp {\n  init_worker_by_lua_block {\n    local ipc = require \"ngx.ipc\"\n    ipc.receive(\"hello\", function(data)\n      ngx.log(ngx.ALERT, \"sender\" .. ipc.sender .. \" says \" .. data)\n      \n      ipc.reply(\"reply\", \"hello to you too. you said \" .. data)\n      \n    end)\n    \n    ipc.receive(\"reply\", function(data) \n      ngx.log(ngx.ALERT, tostring(ipc.sender) .. \" replied \" .. data)\n    end) \n  }\n  \n  server {\n    listen       80;\n    \n    location ~ /send/(\\d+)/(.*)$ {\n      set $dst_pid $1;\n      set $data $2;\n      content_by_lua_block {\n        local ipc = require \"ngx.ipc\"\n        local ok, err = ipc.send(ngx.var.dst_pid, \"hello\", ngx.var.data)\n        if ok then\n          ngx.say(\"Sent alert to pid \" .. ngx.var.dst_pid);\n        else\n          ngx.status = 500\n          ngx.say(err)\n        end\n      }\n    }\n    \n    location ~ /broadcast/(.*)$ {\n      set $data $1;\n      content_by_lua_block { \n        local ipc = require \"ngx.ipc\"\n        ipc.broadcast(\"hello\", ngx.var.data)\n      }\n    }\n    \n  }\n}\n\n```\n\n# How it works\n\nIPC alerts are split into 4K packets and delivered to workers via Unix pipes. On the receiving end, a persistent timer started with `ngx.timer.at` hangs around waiting to be manually triggered by the reading IPC event handler, and thes is re-added to wait for the next alert. A simple hack in concept, but a bit convoluted in implementation.\n\n# Speed\n\nIt's pretty fast. On an i5-2500K (2 core, 4 thread) running Nginx with the Lua module built with Luajit, here are the results of my benchmarks:\n - 5 workers, 10b alerts: 220K alerts/sec\n - 5 workers, 10Kb alerts: 110K alerts/sec\n - 20 workers, 10b alerts: 220K alerts/sec\n - 20 workers, 10Kb alerts: 33K alerts/sec\n\n\n\n\n","funding_links":[],"categories":["Modules"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslact%2Fngx_lua_ipc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslact%2Fngx_lua_ipc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslact%2Fngx_lua_ipc/lists"}