{"id":13777649,"url":"https://github.com/upyun/lua-resty-sync","last_synced_at":"2026-04-01T18:31:40.238Z","repository":{"id":96328725,"uuid":"107070396","full_name":"upyun/lua-resty-sync","owner":"upyun","description":"Synchronizing data based on version changes","archived":false,"fork":false,"pushed_at":"2018-01-03T10:59:43.000Z","size":11,"stargazers_count":41,"open_issues_count":1,"forks_count":6,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-03-26T17:35:53.255Z","etag":null,"topics":["lua-resty"],"latest_commit_sha":null,"homepage":null,"language":"Lua","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/upyun.png","metadata":{"files":{"readme":"README.markdown","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}},"created_at":"2017-10-16T02:48:37.000Z","updated_at":"2022-11-13T19:26:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"f4d8c861-05fe-4534-a69e-71188751cbf2","html_url":"https://github.com/upyun/lua-resty-sync","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/upyun%2Flua-resty-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upyun%2Flua-resty-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upyun%2Flua-resty-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upyun%2Flua-resty-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/upyun","download_url":"https://codeload.github.com/upyun/lua-resty-sync/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225043181,"owners_count":17411944,"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":["lua-resty"],"created_at":"2024-08-03T18:00:46.707Z","updated_at":"2026-04-01T18:31:40.193Z","avatar_url":"https://github.com/upyun.png","language":"Lua","funding_links":[],"categories":["Libraries"],"sub_categories":[],"readme":"Name\n====\n\nlua-resty-sync - synchronizing data based on version changes\n\nTable of Contents\n=================\n\n* [Name](#name)\n* [Synopsis](#synopsis)\n* [Description](#description)\n* [Status](#status)\n* [Methods](#methods)\n    + [new](#new)\n    + [register](#register)\n    + [start](#start)\n    + [get_version](#get_version)\n    + [get_data](#get_data)\n    + [get_last_modified_time](#get_last_modified_time)\n* [TODO](#todo)\n* [Author](#author)\n* [Copyright and License](#copyright-and-license)\n\nSynopsis\n=======\n\n```nginx\n\nhttp {\n    lua_shared_dict sync 5m;\n    lua_shared_dict locks 1m;\n\n    init_worker_by_lua_block {\n        local sync = require \"resty.sync\"\n\n        local syncer, err = sync.new(5, \"sync\")\n        if not syncer then\n            ngx.log(ngx.WARN, \"failed to create sync object: \", err)\n            return\n        end\n\n        local callback = function(mode)\n            if mode == sync.ACTION_DATA then\n                -- GET DATA\n                return \"data \" .. math.random(100) -- just some fake data\n            else\n                -- GET VERSION\n                return \"version \" .. math.random(100)\n            end\n        end\n\n        -- register some tasks\n        syncer:register(callback, \"ex1\")\n\n        -- start to run\n        syncer:start()\n\n        -- save it\n        SYNCER = syncer\n    }\n\n    server {\n        server_name _;\n        listen *:9080;\n\n        location = /t {\n            content_by_lua_block {\n                local sync = require \"resty.sync\"\n\n                local syncer = SYNCER\n\n                local version, err = syncer:get_version(\"ex1\")\n                if not version then\n                    ngx.log(ngx.WARN, \"failed to fetch version: \", err)\n                    return\n                end\n\n                local data, err = syncer:get_data(\"ex1\")\n\n                if not data then\n                    ngx.log(ngx.WARN, \"failed to fetch data: \", err)\n                    return\n                end\n\n                ngx.say(\"task ex1, data: \", data, \" and version: \", version)\n\n                ngx.sleep(5)\n\n                -- after 5s\n                local version2, err = syncer:get_version(\"ex1\")\n                if not version2 then\n                \tngx.log(ngx.WARN, \"failed to fetch version: \", err)\n                \treturn\n                end\n\n                local data2, err = syncer:get_data(\"ex1\")\n\n                if not data2 then\n                \tngx.log(ngx.WARN, \"failed to fetch data: \", err)\n                \treturn\n                end\n\n                ngx.say(\"after 5s, task ex1, data: \", data2, \" and version: \", version2)\n            }\n        }\n    }\n}\n```\n\nDescription\n===========\n\nThis lua-resty library help you to synchronize data(from redis, mysql,\nmemcached and so on) based on the version changes.  \n\nIt will check the freshness by comparing the version cached by itself(stored in shared memory) and the one from your external suits,\n data will be updated when the cached one is stale or for the first time.\nSee the [Synopsis](#synopsis) and [Methods](#methods) for learning how to use this library.\n\nNote this lua module relies on [lua-resty-lock](https://github.com/openresty/lua-resty-lock).\n\n\nStatus\n======\n\nProbably production ready in most cases, though not yet proven in the wild.  \nPlease check the issues list and let me know if you have any problems /\nquestions.\n\n\nMethods\n=======\n\nnew\n---\n\n**syntax:** *local syncer, err = sync.new(interval, shm)*  \n\n**phase:** *init_worker*  \n\n\nCreate and return an instance of the sync.\n\nThe first argument, `interval`, indicates the interval of two successive\noperations(in seconds), which shall be greater than 0.  \nThe second argument `shm`, holds a Lua string, represents a shared\nmemory.\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.\n\nregister\n-------\n\n**syntax:** *local ok, err = syncer:register(callback, tag)*  \n\n**phase:** *init_worker*  \n\n\nRegister a task to the instance `syncer` which created by [new](#new).\n\nThe first argument `callback`, can be any Lua function which will be invoked later in a background \"light thread\".  \nThe callback function not only used for capturing data, but also used for fetching version.  \n\nOnly one argument `mode` can be passed to this function and the value always is:\n\n* sync.ACTION_DATA - capturing data this time.\n* sync.ACTION_VERSION - fetching version this time.\n\n\nThe second argument `tag` is a Lua string which is used for distinguishing different tasks,  \nso it can't be duplicate with one task registered previously.\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.\n\nstart\n=====\n\n**syntax:** *local ok, err = syncer:start()*\n\n**phase:** *init_worker*\n\nLet the instance `syncer` starts to work. Note there will be only one timer created among all workers.  \nThe uniqueness is kept throughout your service's lifetime even the timer owner worker is crash or nginx reload happens.  \n\nCallback in this instance will be run orderly(accroding the order of register).\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.\n\nget_version\n-----------\n\n**syntax:** *local version, err = syncer:get_version(tag)*\n\n**phase**: *set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, body_filter_by_lua, log_by_lua,*  \n*ngx.timer.\\*, balancer_by_lua, ssl_certificate_by_lua, ssl_session_fetch_by_lua, ssl_session_store_by_lua*\n\nGet the current version of one task(specified by `tag`).\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.  \n\nIn particually, `nil` and `\"no data\"` will be given when there is no data.\n\nget_data\n--------\n\n**syntax:** *local data, err = syncer:get_data(tag)*\n\n**phase**: *set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, body_filter_by_lua, log_by_lua,*  \n*ngx.timer.\\*, balancer_by_lua, ssl_certificate_by_lua, ssl_session_fetch_by_lua, ssl_session_store_by_lua*\n\nGet the current data of one task(specified by `tag`).\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.  \n\nIn particually, `nil` and `\"no data\"` will be given when there is no data.\n\nget_last_modified_time\n----------------------\n\n**syntax:** *local timestamp, err = syncer:get_last_modified_time(tag)*\n\n**phase**: *set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, body_filter_by_lua, log_by_lua,*  \n    *ngx.timer.\\*, balancer_by_lua, ssl_certificate_by_lua, ssl_session_fetch_by_lua, ssl_session_store_by_lua*\n\nGet the last update time(unix timestamp) of one task(specified by `tag`).\n\nIn the case of failure, `nil` and a Lua string described the corresponding error will be given.  \n\nIn particually, `nil` and `\"no data\"` will be given when there is no data.\n\n\nTODO\n====\n\n* Do the updates cocurrently in one sync instance.\n\n\nAuthor\n======\n\nAlex Zhang(张超) zchao1995@gmail.com, UPYUN Inc.\n\n\nCopyright and License\n=====================\n\nThe bundle itself is licensed under the 2-clause BSD license.\n\nCopyright (c) 2017, UPYUN(又拍云) Inc.\n\nThis module is licensed under the terms of the BSD license.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\n\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupyun%2Flua-resty-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fupyun%2Flua-resty-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupyun%2Flua-resty-sync/lists"}