• Stars
    star
    67
  • Rank 446,319 (Top 10 %)
  • Language
    Lua
  • License
    MIT License
  • Created almost 10 years ago
  • Updated almost 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Pure Lua Cassandra client using CQL binary protocol

This repo is not being actively maintained. I highly recommend that you try lua-cassandra

lua-resty-cassandra

Build Status Coverage Status Module Version Join the chat at https://gitter.im/jbochi/lua-resty-cassandra

Pure Lua Cassandra client using CQL binary protocol v2.

It is 100% non-blocking if used in Nginx/Openresty but can also be used with luasocket.

Installation

Luarocks

Installation through luarocks is recommended:

$ luarocks install cassandra

Manual

Copy the src/ folder and require cassandra.lua.

Usage

Overview:

local cassandra = require "cassandra"

local session = cassandra.new()
session:set_timeout(1000) -- 1000ms timeout

local connected, err = session:connect("127.0.0.1", 9042)

session:set_keyspace("lua_tests")

-- simple query
local table_created, err = session:execute [[
  CREATE TABLE users(
    user_id uuid PRIMARY KEY,
    name varchar,
    age int
  )
]]

-- query with arguments
local ok, err = session:execute([[
  INSERT INTO users(name, age, user_id) VALUES(?, ?, ?)
]], {"John O'Reilly", 42, cassandra.uuid("1144bada-852c-11e3-89fb-e0b9a54a6d11")})


-- select statement
local users, err = session:execute("SELECT name, age, user_id from users")

assert(1 == #users)
local user = users[1]
ngx.say(user.name) -- "John O'Reilly"
ngx.say(user.user_id) -- "1144bada-852c-11e3-89fb-e0b9a54a6d11"
ngx.say(user.age) -- 42

You can check more examples in the tests or here.

Socket methods

session, err = cassandra.new()

Creates a new session. Create a socket with the cosocket API if available, fallback on luasocket otherwise.

Return values:

  • session: A lua-resty-cassandra session.
  • err: Any error encountered during the socket creation.

session:set_timeout(timeout)

Sets timeout (in miliseconds). Uses Nginx tcpsock:settimeout.

Parameters:

  • timeout: A number being the timeout in miliseconds

ok, err = session:connect(contact_points, port)

Connects to a single or multiple hosts at the given port.

Parameters:

  • contact_points: A string or an array of strings (hosts) to connect to.
    • Note: If you wish to give a different port to one of those hosts, format the string as: "host:port" for that specific contact point. The specified port value will overwrite the port argument of connect for that contact point.
  • port: The port number. Default: 9042.

Return values:

  • ok: true if connected, false otherwise. Nil of the session doesn't have a socket.
  • err: Any encountered error.

ok, err = session:set_keepalive(max_idle_timeout, pool_size) -- Nginx only

Puts the current Cassandra connection immediately into the ngx_lua cosocket connection pool.

Note: Only call this method in the place you would have called the close method instead. Calling this method will immediately turn the current cassandra session object into the closed state. Any subsequent operations other than connect() on the current objet will return the closed error.

Parameters:

  • max_idle_timeout: Max idle timeout (in ms) when the connection is in the pool
  • pool_size: Maximal size of the pool every nginx worker process.

Return values:

  • ok: 1 if success, nil otherwise.
  • err: Encountered error if any

times, err = session:get_reused_times() -- Nginx only

This method returns the (successfully) reused times for the current connection. In case of error, it returns nil and a string describing the error.

Note: If the current connection does not come from the built-in connection pool, then this method always returns 0, that is, the connection has never been reused (yet). If the connection comes from the connection pool, then the return value is always non-zero. So this method can also be used to determine if the current connection comes from the pool.

Return values:

  • times: Number of times the current connection was successfully reused, nil if error
  • err: Encountered error if any

ok, err = session:close()

Closes the current connection and returns the status.

Return values:

  • ok: 1 if success, nil otherwise.
  • err: Encountered error if any

Client methods

All errors returned by functions in this section are tables with the following properties:

  • code: A string from one of the error_codes in cassandra.contants.
  • raw_message: The error message being returned by Cassandra.
  • message: A constructed error message with code + raw_message.

Error tables implement the __tostring method and are thus printable. A stringified error table will outputs its message property.

ok, err = session:set_keyspace(keyspace_name)

Sets session keyspace to the given keyspace_name.

Parameters:

  • keyspace_name: Name of the keyspace to use.

Return values:

See :execute()

stmt, err = session:prepare(query, options)

Prepare a statement for later execution.

Parameters:

  • query: A string representing a query to prepare.
  • options: The same options available on :execute().

Return values:

  • stmt: A prepareed statement to be used by :execute(), nil if the preparation failed.
  • err: Encountered error if any.

result, err = session:execute(query, args, options)

Execute a query or previously prepared statement.

Parameters:

  • query: A string representing a query or a previously prepared statement.
  • args: An array of arguments to bind to the query. Those arguments can be type annotated (example: cassandra.bigint(4). If there is no annotation, the driver will try to infer a type. Since integer numbers are serialized as int with 4 bytes, Cassandra would return an error if we tried to insert it in a bigint column.
  • options is a table of options:
    • consistency_level: for example cassandra.consistency.ONE
    • tracing: if set to true, enables tracing for this query. In this case, the result table will contain a key named tracing_id with an uuid of the tracing session.
    • page_size: Maximum size of the page to fetch (default: 5000).
    • auto_paging: If set to true, execute will return an iterator. See the example below on how to use auto pagination.

Return values:

  • result: A table containing the result of this query if successful, ni otherwise. The table can contain additional keys:
    • type: Type of the result set, can either be "VOID", "ROWS", "SET_KEYSPACE" or "SCHEMA_CHANGE".
    • meta: If the result type is "ROWS" and the result has more pages that haven't been returned, this property will contain 2 values: has_more_pages and paging_state. See the example below on how to use pagination.
  • err: Encountered error if any.

batch, err = cassandra.BatchStatement(type)

Initialized a batch statement. See the example below on how to use batch statements and this for informations about the type of batch to use.

Parameters:

  • type: The type of batch statement. Can be ony of those:
    • cassandra.batch_types.LOGGED (default)
    • cassandra.batch_types.UNLOGGED
    • cassandra.batch_types.COUNTER

Return values:

  • batch: An empty batch statement on which to add operations.
  • err: Encountered error if any.

batch:add(query, args)

Add an operation to a batch statement. See the example below on how to use batch statements.

Parameters:

  • query: A string representing a query or a previously prepared statement.
  • args: An array of arguments to bind to the query, similar to :execute().

trace, err = session:get_trace(result)

Return the trace of a given result, if possible.

Parameters:

  • result: A previous query result.

Return values:

trace: is a table with the following keys (from system_traces.sessions and system_traces.events system tracing tables:

  • coordinator
  • duration
  • parameters
  • request
  • started_at
  • events: an array of tables with the following keys:
    • event_id
    • activity
    • source
    • source_elapsed
    • thread

err: Encountered error if any.

Examples

Batches:

-- Create a batch statement
local batch = cassandra.BatchStatement()

-- Add a query
batch:add("INSERT INTO users (name, age, user_id) VALUES (?, ?, ?)",
          {"James", 32, cassandra.uuid("2644bada-852c-11e3-89fb-e0b9a54a6d93")})

-- Add a prepared statement
local stmt, err = session:prepare("INSERT INTO users (name, age, user_id) VALUES (?, ?, ?)")
batch:add(stmt, {"John", 45, cassandra.uuid("1144bada-852c-11e3-89fb-e0b9a54a6d11")})

-- Execute the batch
local result, err = session:execute(batch)

Pagination might be very useful to build web services:

-- Assuming our users table contains 1000 rows

local query = "SELECT * FROM users"
local rows, err = session:execute(query, nil, {page_size = 500}) -- default page_size is 5000

assert.same(500, #rows) -- rows contains the 500 first rows

if rows.meta.has_more_pages then
  local next_rows, err = session:execute(query, nil, {paging_state = rows.meta.paging_state})

  assert.same(500, #next_rows) -- next_rows contains the next (and last) 500 rows
end

Automated pagination:

-- Assuming our users table now contains 10.000 rows

local query = "SELECT * FROM users"

for _, rows, page, err in session:execute(query, nil, {auto_paging=true}) do
  assert.same(5000, #rows) -- rows contains 5000 rows on each iteration in this case
  -- page: will be 1 on the first iteration, 2 on the second
  -- err: in case any fetch returns an error
  -- _: (the first for argument) is the current paging_state used to fetch the rows
end

Running unit tests

We use busted and require luasocket to mock ngx.socket.tcp(). To run the tests, start a local cassandra instance and run:

$ luarocks install busted
$ make test

Running coverage

$ luarocks install luacov
$ make coverage

Report will be in ./luacov.report.out.

Running linting

$ luarocks install luacheck
$ make lint

Contributors

Juarez Bochi (@jbochi)

Thibault Charbonnier (@thibaultCha) -> Several contributions, including paging support, improved batch statements, better documentation, specs and code style.

Leandro Moreira (@leandromoreira) -> Added support for doubles

Marco Palladino (@thefosk)

More Repositories

1

gifstreaming

Live video streaming server using animated GIFs, Python and Node.js
Python
155
star
2

live_thumb

Live thumbnail using MJPEG and nginx_push_stream
Python
100
star
3

hls-loop

Infinite HLS live loop server
TypeScript
49
star
4

cep

Biblioteca em Python para consulta de CEPs via site dos correios
Python
36
star
5

facts

Matrix Factorization based recsys in Golang. Because facts are more important than ever
Go
33
star
6

bullock

Distributed lock for Python using Redis
Python
31
star
7

bazinga

Bazinga is an incremental test runner plugin for nose
Python
27
star
8

planets

Gravity simulation in javascript
JavaScript
25
star
9

sandals

SQL for Pandas
Python
25
star
10

vi-video

Edit videos with vi or your favorite text editor
Python
18
star
11

duelo

An incomplete node.js game
JavaScript
16
star
12

strogonoff

Steganography with Go
Go
11
star
13

hackaton_rank

Top projetos em número de commits do hackinpoa
Python
11
star
14

media-source-playground

Media source extensions playground
9
star
15

feiradetector

Feira da fruta detector
Python
7
star
16

gene

Distributed Genetic Algorithm in Clojure
Clojure
6
star
17

infraero

Biblioteca para fazer scrap do site da infraero
Python
5
star
18

lua_jit_extract_audio

Example of how to extract audio with lua jit and libavcodec (ffmpeg)
C
5
star
19

mgof

Multinomial goodness of fit in Redis for Anomaly Detection
Lua
5
star
20

github-recs

GitHub repositories recommendations using Go and AppEngine
Go
4
star
21

python-data-science

Tutorial data science com python
4
star
22

similarnn

Similarity server using topic modelling and approximate nearest neighbours
Python
4
star
23

lastfm

Python wrapper for Last.fm API
Python
4
star
24

fms

FMS (Flash Media Server) API Client
Python
3
star
25

scrum-you

Another to-do list application for Google App Engine using Flask
Python
3
star
26

freecep

Retomando posse dos dados públicos de CEP
JavaScript
3
star
27

to-a-pe

Google transit data feed website for Google App Engine
Python
2
star
28

Project-Euler

Practicing TDD, Java, and JUnit with Project Euler problems
Java
2
star
29

codejam

Google Code Jam
C
2
star
30

depoisdavirgula

Controle financeiro no Google App Engine
JavaScript
2
star
31

parallel_redis

Redis with support for concurrent scripts in Lua
C
2
star
32

lua-rpc

toy project for lua rpc
Lua
1
star
33

video-clock

Create a video with a clock
Python
1
star
34

jbochi.github.com

Ruby
1
star
35

evo

Python evostream client
Python
1
star
36

recsyschallenge2015

Visualization of recsys challenge for 2015
1
star
37

strogonoff-demo

Strogonoff demo on Google Application Engine's Go runtime
Go
1
star
38

laugh

Ruby
1
star