{"id":13420569,"url":"https://github.com/carlosabalde/libvmod-redis","last_synced_at":"2025-03-23T04:06:36.251Z","repository":{"id":19963946,"uuid":"23230881","full_name":"carlosabalde/libvmod-redis","owner":"carlosabalde","description":"VMOD using the synchronous hiredis library API to access Redis servers from VCL.","archived":false,"fork":false,"pushed_at":"2024-09-17T12:30:03.000Z","size":1258,"stargazers_count":80,"open_issues_count":2,"forks_count":21,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-09-17T15:19:11.489Z","etag":null,"topics":["redis","varnish","vmod"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"LineageOS/android_device_lge_g4-common","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlosabalde.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"COPYING","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":"2014-08-22T15:52:54.000Z","updated_at":"2024-09-17T12:19:47.000Z","dependencies_parsed_at":"2024-01-05T16:28:59.150Z","dependency_job_id":"0d1c3f28-d156-4620-9194-f4d2f318a60d","html_url":"https://github.com/carlosabalde/libvmod-redis","commit_stats":null,"previous_names":[],"tags_count":110,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosabalde%2Flibvmod-redis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosabalde%2Flibvmod-redis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosabalde%2Flibvmod-redis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosabalde%2Flibvmod-redis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlosabalde","download_url":"https://codeload.github.com/carlosabalde/libvmod-redis/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245052673,"owners_count":20553172,"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":["redis","varnish","vmod"],"created_at":"2024-07-30T22:01:36.472Z","updated_at":"2025-03-23T04:06:36.228Z","avatar_url":"https://github.com/carlosabalde.png","language":"C","funding_links":[],"categories":["TODO scan for Android support in followings"],"sub_categories":[],"readme":"\n.. image:: https://github.com/carlosabalde/libvmod-redis/actions/workflows/main.yml/badge.svg?branch=master\n   :alt: GitHub Actions CI badge\n   :target: https://github.com/carlosabalde/libvmod-redis/actions\n.. image:: https://codecov.io/gh/carlosabalde/libvmod-redis/branch/master/graph/badge.svg\n   :alt: Codecov badge\n   :target: https://codecov.io/gh/carlosabalde/libvmod-redis\n\nVMOD using the `synchronous hiredis library API \u003chttps://github.com/redis/hiredis\u003e`_ to access Redis servers from VCL. For an alternative using libvalkey + Valkey, please check the `libvmod-valkey VMOD \u003chttps://github.com/carlosabalde/libvmod-valkey\u003e`_ project.\n\nHighlights:\n\n* **Full support for execution of LUA scripts** (i.e. ``EVAL`` command), including optimistic automatic execution of ``EVALSHA`` commands.\n* **All Redis reply data types are supported**, including partial support to access to components of simple (i.e. not nested) array replies.\n* **Redis pipelines are not (and won't be) supported**. LUA scripting, which is fully supported by the VMOD, it's a much more flexible alternative to pipelines for atomic execution and minimizing latency. Pipelines are hard to use and error prone, specially when using the ``WATCH`` command.\n* **Support for classic Redis deployments** using multiple replicated Redis servers **and for clustered deployments based on Redis Cluster**.\n* **Support for multiple databases and multiple Redis connections**, local to each Varnish worker thread, or shared using one or more pools.\n* **Support for smart command execution**, selecting the destination server according with the preferred role (i.e. master or slave) and with distance and healthiness metrics collected during execution.\n* **Support for Redis Sentinel**, allowing automatic discovery of sick / healthy servers and changes in their roles.\n\nPlease, check out `the project wiki \u003chttps://github.com/carlosabalde/libvmod-redis/wiki\u003e`_ for some extra information and useful links.\n\nLooking for official support for this VMOD? Please, contact `Allenta Consulting \u003chttps://www.allenta.com\u003e`_, a `Varnish Software Premium partner \u003chttps://www.varnish-software.com/partner/allenta-consulting\u003e`_.\n\nSYNOPSIS\n========\n\nimport redis;\n\n::\n\n    ##\n    ## Subnets.\n    ##\n\n    Function subnets(STRING masks=\"\")\n\n    ##\n    ## Sentinels.\n    ##\n\n    Function sentinels(\n        STRING locations=\"\",\n        INT period=60,\n        INT connection_timeout=500,\n        INT command_timeout=0,\n        ENUM { RESP2, RESP3, default } protocol=\"default\",\n        BOOL tls=false,\n        STRING tls_cafile=\"\",\n        STRING tls_capath=\"\",\n        STRING tls_certfile=\"\",\n        STRING tls_keyfile=\"\",\n        STRING tls_sni=\"\",\n        STRING password=\"\")\n\n    ##\n    ## Proxy.\n    ##\n\n    # Instance selection.\n    Function VOID use(STRING db)\n\n    # Proxied methods.\n    Method VOID .add_server(..., STRING db=\"\")\n    Function VOID command(..., STRING db=\"\")\n    Function VOID timeout(..., STRING db=\"\")\n    Function VOID retries(..., STRING db=\"\")\n    ...\n    Method STRING .stats(..., STRING db=\"\")\n    Method INT .counter(..., STRING db=\"\")\n\n    ##\n    ## Databases.\n    ##\n\n    # Constructor.\n    Object db(\n        STRING location=\"\",\n        ENUM { master, slave, auto, cluster } type=\"auto\",\n        INT connection_timeout=1000,\n        INT connection_ttl=0,\n        INT command_timeout=0,\n        INT max_command_retries=0,\n        BOOL shared_connections=true,\n        INT max_connections=128,\n        ENUM { RESP2, RESP3, default } protocol=\"default\",\n        BOOL tls=false,\n        STRING tls_cafile=\"\",\n        STRING tls_capath=\"\",\n        STRING tls_certfile=\"\",\n        STRING tls_keyfile=\"\",\n        STRING tls_sni=\"\",\n        STRING user=\"\",\n        STRING password=\"\",\n        INT sickness_ttl=60,\n        BOOL ignore_slaves=false,\n        INT max_cluster_hops=32)\n    Method VOID .add_server(\n        STRING location,\n        ENUM { master, slave, auto, cluster } type)\n\n    # Command execution.\n    Method VOID .command(STRING name)\n    Method VOID .timeout(INT command_timeout)\n    Method VOID .retries(INT max_command_retries)\n    Method VOID .push(STRING arg)\n    Method VOID .execute(BOOL master=true)\n    Method VOID .easy_execute(STRING command, [STRING command_args...], BOOL master=true, INT command_timeout, INT max_command_retries)\n\n    # Access to replies.\n    Method BOOL .replied()\n\n    Method BOOL .reply_is_error()\n    Method BOOL .reply_is_nil()\n    Method BOOL .reply_is_status()\n    Method BOOL .reply_is_integer()\n    Method BOOL .reply_is_boolean()\n    Method BOOL .reply_is_double()\n    Method BOOL .reply_is_string()\n    Method BOOL .reply_is_array()\n\n    Method STRING .get_reply()\n\n    Method STRING .get_error_reply()\n    Method STRING .get_status_reply()\n    Method INT .get_integer_reply()\n    Method BOOL .get_boolean_reply()\n    Method REAL .get_double_reply()\n    Method STRING .get_string_reply()\n\n    Method INT .get_array_reply_length()\n    Method BOOL .array_reply_is_error(INT index)\n    Method BOOL .array_reply_is_nil(INT index)\n    Method BOOL .array_reply_is_status(INT index)\n    Method BOOL .array_reply_is_integer(INT index)\n    Method BOOL .array_reply_is_boolean(INT index)\n    Method BOOL .array_reply_is_double(INT index)\n    Method BOOL .array_reply_is_string(INT index)\n    Method BOOL .array_reply_is_array(INT index)\n    Method STRING .get_array_reply_value(INT index)\n\n    # Other.\n    Method VOID .free()\n    Method STRING .stats(\n        ENUM { json, prometheus } format=\"json\",\n        BOOL stream=0,\n        STRING prometheus_name_prefix=\"vmod_redis_\",\n        BOOL prometheus_default_labels=1,\n        STRING prometheus_extra_labels=\"\")\n    Method INT .counter(STRING name)\n\nEXAMPLES\n========\n\nSingle server\n-------------\n\n::\n\n    sub vcl_init {\n        # VMOD configuration: simple case, keeping up to one Redis connection\n        # per Varnish worker thread.\n        new db = redis.db(\n            location=\"192.168.1.100:6379\",\n            type=master,\n            connection_timeout=500,\n            shared_connections=false,\n            max_connections=1);\n    }\n\n    sub vcl_deliver {\n        # Simple command execution.\n        db.command(\"SET\");\n        db.push(\"foo\");\n        db.push(\"Hello world!\");\n        db.execute();\n\n        # Alternatively, the same can be achieved with one single command\n        db.easy_execute(\"SET\", \"foo\", \"Hello world!\");\n\n        # LUA scripting.\n        db.command(\"EVAL\");\n        db.push({\"\n            redis.call('SET', KEYS[1], ARGV[1])\n            redis.call('SET', KEYS[2], ARGV[1])\n        \"});\n        db.push(\"2\");\n        db.push(\"foo\");\n        db.push(\"bar\");\n        db.push(\"Atomic hello world!\");\n        db.execute();\n\n        # Array replies, checking \u0026 accessing to reply.\n        db.command(\"MGET\");\n        db.push(\"foo\");\n        db.push(\"bar\");\n        db.execute();\n        if ((db.reply_is_array()) \u0026\u0026\n            (db.get_array_reply_length() == 2)) {\n            set resp.http.X-Foo = db.get_array_reply_value(0);\n            set resp.http.X-Bar = db.get_array_reply_value(1);\n        }\n    }\n\nMultiple servers\n----------------\n\n::\n\n    sub vcl_init {\n        # VMOD configuration: master-slave replication, keeping up to two\n        # Redis connections per Varnish worker thread (up to one to the master\n        # server \u0026 up to one to the closest slave server).\n        redis.subnets(\n            masks={\"\n                0 192.168.1.102/32,\n                1 192.168.1.103/32,\n                2 0.0.0.0/32\n            \"});\n        new db = redis.db(\n            location=\"192.168.1.100:6379\",\n            type=master,\n            connection_timeout=500,\n            shared_connections=false,\n            max_connections=2);\n        db.add_server(\"192.168.1.101:6379\", slave);\n        db.add_server(\"192.168.1.102:6379\", slave);\n        db.add_server(\"192.168.1.103:6379\", slave);\n    }\n\n    sub vcl_deliver {\n        # SET submitted to the master server.\n        db.command(\"SET\");\n        db.push(\"foo\");\n        db.push(\"Hello world!\");\n        db.execute();\n\n        # GET submitted to one of the slave servers.\n        db.command(\"GET\");\n        db.push(\"foo\");\n        db.execute(false);\n        set req.http.X-Foo = db.get_string_reply();\n    }\n\nClustered setup\n---------------\n\n::\n\n    sub vcl_init {\n        # VMOD configuration: clustered setup, keeping up to 100 Redis\n        # connections per server, all shared between all Varnish worker threads.\n        # Two initial cluster servers are provided; remaining servers are\n        # automatically discovered.\n        new db = redis.db(\n            location=\"192.168.1.100:6379\",\n            type=cluster,\n            connection_timeout=500,\n            shared_connections=true,\n            max_connections=128,\n            max_cluster_hops=16);\n        db.add_server(\"192.168.1.101:6379\", cluster);\n    }\n\n    sub vcl_deliver {\n        # SET internally routed to the destination server.\n        db.command(\"SET\");\n        db.push(\"foo\");\n        db.push(\"Hello world!\");\n        db.execute();\n\n        # GET internally routed to the destination server.\n        db.command(\"GET\");\n        db.push(\"foo\");\n        db.execute(false);\n        set req.http.X-Foo = db.get_string_reply();\n    }\n\nINSTALLATION\n============\n\nThe source tree is based on autotools to configure the building, and does also have the necessary bits in place to do functional unit tests using the varnishtest tool.\n\n**Beware this project contains multiples branches (master, 4.1, 4.0, etc.). Please, select the branch to be used depending on your Varnish Cache version (Varnish trunk → master, Varnish 4.1.x → 4.1, Varnish 4.0.x → 4.0, etc.).**\n\nDependencies:\n\n* `hiredis \u003chttps://github.com/redis/hiredis\u003e`_ - minimalistic C Redis client library.\n* `libev \u003chttp://software.schmorp.de/pkg/libev.html\u003e`_ - full-featured and high-performance event loop.\n\nCOPYRIGHT\n=========\n\nSee LICENSE for details.\n\nPublic domain implementation of the SHA-1 cryptographic hash function by Steve Reid and embedded in this VMOD (required for the optimistic execution of ``EVALSHA`` commands) has been borrowed from `this project \u003chttps://github.com/clibs/sha1/\u003e`_:\n\n* https://github.com/clibs/sha1/blob/master/sha1.c\n* https://github.com/clibs/sha1/blob/master/sha1.h\n\nBSD's implementation of the CRC-16 cryptographic hash function by Georges Menie \u0026 Salvatore Sanfilippo and embedded in this VMOD (required for the Redis Cluster slot calculation) has been borrowed from the `Redis project \u003chttps://redis.io\u003e`_:\n\n* http://download.redis.io/redis-stable/src/crc16.c\n\nCopyright (c) Carlos Abalde \u003ccarlos.abalde@gmail.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosabalde%2Flibvmod-redis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlosabalde%2Flibvmod-redis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosabalde%2Flibvmod-redis/lists"}