redify

module
v0.4.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2023 License: Apache-2.0

README

Redify (Any database as redis)

Testing Status Publish Docker Status Coverage Status Go Report Card GoDoc

License Apache 2.0

Redify is the optimized key-value proxy for quick access and cache of any other database throught Redis and/or HTTP protocol. Can be used for any kind of content web project to accelerate access to data to make it faster, simpler and more reliable.

Modern websites it's a banch of small services which use many different databases. Almost always for data reading used some key-value storage for caches. The project will help to create more simple content website without using connection to R_DBMS with simple wide used protocol without implementation of complex application controllers and custom caches.

Build project

APP_BUILD_TAGS=pgx,clickhouse,mysql,mssql,kafka,redispub,nats make build
redify --conf docker/example.config.yml

Run in docker

docker run -v ./my.config.yml:/config.yml -it --rm demdxx/refidy:latest --conf /config.yml

Config example

cache:
  # redis://host:port/{dbnum}?max_retries=0&min_retry_backoff=10s&max_retry_backoff=10s&dial_timeout=3s&read_timeout=3s&write_timeout=3s&pool_fifo=false&pool_size=10&min_idle_conns=60s&max_conn_age=60s&pool_timeout=300s&idle=100s&idle_check_frequency=3s&ttl=200s
  connect: "memory"
  size: 1000 # Max capacity
  ttl: 60s # Seconds
sources:
  - connect: "postgres://dbuser:password@pgdb:5432/project?sslmode=disable"
    # Predefined in the postgresql notification channel
    notify_channel: redify_update
    binds:
    - dbnum: 0
      key: "post_{{slug}}"
      get_query: "SELECT * FROM posts WHERE slug = {{slug}} AND deleted_at IS NULL LIMIT 1"
      list_query: "SELECT slug FROM posts WHERE deleted_at IS NULL"
    - dbnum: 1
      # Automaticaly prepare requests for table `users` with key field `username`
      key: "user_{{username}}"
      table_name: "users"
      readonly: yes
    - dbnum: 2
      key: "document_{{type}}_{{slug}}"
      get_query: |
        SELECT * FROM documents WHERE type={{type}} AND slug={{slug}} AND deleted_at IS NULL LIMIT 1
      list_query: |
        SELECT type, slug FROM documents WHERE deleted_at IS NULL
      upsert_query: |
        INSERT INTO documents (slug, type, title, content)
          VALUES ({{slug}},{{type}},{{title}},{{content}})
          ON CONFLICT (slug, type) DO UPDATE SET title={{title}}, content={{content}}, deleted_at=NULL
      del_query: |
        UPDATE documents SET deleted_at=NOW() WHERE type={{type}} AND slug={{slug}}
  - connect: "mysql://dbuser:password@mysql:3306/project"
    binds:
    - dbnum: 0
      key: "wp_post_{{slug}}"
      get_query: "SELECT * FROM wp_posts WHERE slug = {{slug}} AND deleted_at IS NULL LIMIT 1"
      list_query: "SELECT slug FROM wp_posts WHERE deleted_at IS NULL"
  - connect: nats://nats:4442/group?topics=news
    binds:
    - dbnum: 0
      key: news_notify

Redis using example

For using of Redis protocol.

export SERVER_REDIS_LISTEN=:8080
export SERVER_REDIS_READ_TIMEOUT=120s
> redis-cli -p 8081 -h hostname
hostname:8081> keys *o*
1) "post_hello"
2) "post_bye"
3) "document_docx_main"
4) "document_pdf_help"
hostname:8081> get post_bye
"{\"content\":\"Bye everyone\",\"created_at\":\"2021-11-06T20:03:56.218629Z\",\"deleted_at\":null,\"id\":4,\"slug\":\"bye\",\"title\":\"Bye world\",\"updated_at\":\"2021-11-06T20:03:56.218629Z\"}"
hostname:8081> hgetall post_hello
 1) "content"
 2) "Hello everyone"
 3) "created_at"
 4) "2021-11-06T20:03:56.218629Z"
 5) "deleted_at"
 6) "null"
 7) "id"
 8) "3"
 9) "slug"
10) "hello"
11) "title"
12) "Hello world"
13) "updated_at"
14) "2021-11-06T20:03:56.218629Z"
hostname:8081> hget post_hello title
"Hello world"

HTTP example

For using of HTTP protocol.

export SERVER_HTTP_LISTEN=:8080
export SERVER_HTTP_READ_TIMEOUT=120s

GET /:dbnum/:key

curl -XGET "http://localhost:8080/0/post_hello"
{"status":"OK", "result":{"content":"Hello everyone","created_at":"2021-11-06T20:03:56.218629Z","deleted_at":null,"id":3,"slug":"hello","title":"Hello world","updated_at":"2021-11-06T20:03:56.218629Z"}}

PUT /:dbnum/:key POST /:dbnum/:key

curl -d "@data.json" -XPOST "http://localhost:8080/0/list/post_hello"
{"status":"OK"}

GET /:dbnum/list/:pattern

curl -XGET "http://localhost:8080/0/list/post_*"
{"status":"OK", "result":["post_post-1","post_post-2","post_hello","post_bye"]}

DELETE /:dbnum/:key

curl -XDELETE "http://localhost:8080/0/post_hello"
{"status":"OK"}

Cache invalidation notifications

PostgreSQL

PostgreSQL supports pg_notify precedure to notify about any kind of changes in data.

CREATE OR REPLACE FUNCTION notify_event() RETURNS TRIGGER AS $$

    DECLARE
        data json;
        notification json;

    BEGIN

        -- Convert the old or new row to JSON, based on the kind of action.
        -- Action = DELETE?             -> OLD row
        -- Action = INSERT or UPDATE?   -> NEW row
        IF (TG_OP = 'DELETE') THEN
            data = row_to_json(OLD);
        ELSE
            data = row_to_json(NEW);
        END IF;

        -- Contruct the notification as a JSON string.
        notification = json_build_object(
                          'table',TG_TABLE_NAME,
                          'action', TG_OP,
                          'data', data);

        -- Execute pg_notify(channel, notification)
        PERFORM pg_notify('redify_update', notification::text);

        -- Result is ignored since this is an AFTER trigger
        RETURN NULL;
    END;

$$ LANGUAGE plpgsql;

CREATE TRIGGER products_notify_event
AFTER INSERT OR UPDATE OR DELETE ON products
    FOR EACH ROW EXECUTE PROCEDURE notify_event();

Event streaming

In some cases, it will be convenient to use storage keys as a mechanism for publishing events to message publishing systems (queues). It can be used to publish intrasystem events or form pending actions.

Build
APP_BUILD_TAGS=kafka,redispub,nats make build
Config
sources:
  # (kafka|nats|redispub)://hostname:port/group_name?topics=name_in_stream
  - connect: nats://nats:4442/group?topics=news
    binds:
    - dbnum: 0
      key: news_notify
Using
hostname:8081> set news_notify '{"action":"view","id":100,"ts":199991229912}'
OK

Support Redis commands

  • SELECT [dbnum]
  • KEYS [pattern]
  • GET key
  • MGET key1 key2 ... keyN
  • HGET key fieldname
  • HGETALL key
  • SET key value
  • MSET key1 value1 key2 value2 ... keyN valueN
  • PING
  • QUIT

TODO

  • PGX PostgreSQL driver support
  • MySQL driver support
  • Sqlite driver support
  • MSSQL driver support
  • Oracle driver support
  • Stream Publishing driver (Kafka,NATS,Redis Pub)
  • Clickhouse driver support
  • Add personal cache to every bind separately
  • Cassandra driver support
  • MongoDB driver support
  • NextJS application example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL