Skip to content

Commit

Permalink
Merge pull request #47 from thibaultCha/improve-errors
Browse files Browse the repository at this point in the history
improve and document cassandra errors
  • Loading branch information
jbochi committed Mar 25, 2015
2 parents cd70ebf + e03754b commit 3002cbb
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 23 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ Closes the current connection and returns the status.
## 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`.
Expand Down
14 changes: 10 additions & 4 deletions spec/functional_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package.path = "src/?.lua;spec/?.lua;" .. package.path

_G.ngx = require("fake_ngx")
local cassandra = require("cassandra")
local constants = require("cassandra.constants")

describe("cassandra", function()

Expand Down Expand Up @@ -180,11 +181,16 @@ describe("cassandra", function()
end)

describe("Keyspace", function()
it("should catch errors", function()
it("should catch (rich) errors", function()
local ok, err = session:set_keyspace("invalid_keyspace")
assert.same("Invalid", err.code)
assert.same(constants.error_codes.INVALID, err.code)
assert.same("Keyspace 'invalid_keyspace' does not exist", err.raw_message)
assert.same([[Cassandra returned error (Invalid): "Keyspace 'invalid_keyspace' does not exist"]], tostring(err))

-- Test concatenation of an error
assert.same([[Cassandra returned error (Invalid): "Keyspace 'invalid_keyspace' does not exist"]] .. "foo", err .. "foo")
assert.same("foo" .. [[Cassandra returned error (Invalid): "Keyspace 'invalid_keyspace' does not exist"]], "foo" .. err)
assert.same([[Cassandra returned error (Invalid): "Keyspace 'invalid_keyspace' does not exist"]]..[[Cassandra returned error (Invalid): "Keyspace 'invalid_keyspace' does not exist"]], err .. err)
end)

it("should be possible to use a namespace", function()
Expand Down Expand Up @@ -229,7 +235,7 @@ describe("cassandra", function()
)
]]
assert.is_not_true(table_created)
assert.same("Already_exists", err.code)
assert.same(constants.error_codes.ALREADY_EXISTS, err.code)
assert.same('Cannot add already existing column family "users" to keyspace "lua_tests"', err.raw_message)
assert.same('Cassandra returned error (Already_exists): "Cannot add already existing column family "users" to keyspace "lua_tests""', tostring(err))
end)
Expand Down Expand Up @@ -265,7 +271,7 @@ describe("cassandra", function()
local ok, err = session:execute([[
INSERT INTO users (name, age, user_id)
VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
]], {}, {consistency_level=cassandra.consistency.TWO})
]], {}, {consistency_level=cassandra.consistency.TWO})
assert.same('Cassandra returned error (Unavailable exception): "Cannot achieve consistency level TWO"', tostring(err))
end)

Expand Down
51 changes: 35 additions & 16 deletions src/cassandra/constants.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
local error_codes = {
SERVER = 0x0000,
PROTOCOL = 0x000A,
BAD_CREDENTIALS = 0x0100,
UNAVAILABLE_EXCEPTION = 0x1000,
OVERLOADED = 0x1001,
IS_BOOTSTRAPPING = 0x1002,
TRUNCATE_ERROR = 0x1003,
WRITE_TIMEOUT = 0x1100,
READ_TIMEOUT = 0x1200,
SYNTAX_ERROR = 0x2000,
UNAUTHORIZED = 0x2100,
INVALID = 0x2200,
CONFIG_ERROR = 0x2300,
ALREADY_EXISTS = 0x2400,
UNPREPARED = 0x2500
}

return {
version_codes = {
REQUEST=0x02,
Expand Down Expand Up @@ -58,22 +76,23 @@ return {
PREPARED=0x04,
SCHEMA_CHANGE=0x05
},
error_codes = {
[0x0000]="Server error",
[0x000A]="Protocol error",
[0x0100]="Bad credentials",
[0x1000]="Unavailable exception",
[0x1001]="Overloaded",
[0x1002]="Is_bootstrapping",
[0x1003]="Truncate_error",
[0x1100]="Write_timeout",
[0x1200]="Read_timeout",
[0x2000]="Syntax_error",
[0x2100]="Unauthorized",
[0x2200]="Invalid",
[0x2300]="Config_error",
[0x2400]="Already_exists",
[0x2500]="Unprepared"
error_codes = error_codes,
error_codes_translation = {
[error_codes.SERVER]="Server error",
[error_codes.PROTOCOL]="Protocol error",
[error_codes.BAD_CREDENTIALS]="Bad credentials",
[error_codes.UNAVAILABLE_EXCEPTION]="Unavailable exception",
[error_codes.OVERLOADED]="Overloaded",
[error_codes.IS_BOOTSTRAPPING]="Is_bootstrapping",
[error_codes.TRUNCATE_ERROR]="Truncate_error",
[error_codes.WRITE_TIMEOUT]="Write_timeout",
[error_codes.READ_TIMEOUT]="Read_timeout",
[error_codes.SYNTAX_ERROR]="Syntax_error",
[error_codes.UNAUTHORIZED]="Unauthorized",
[error_codes.INVALID]="Invalid",
[error_codes.CONFIG_ERROR]="Config_error",
[error_codes.ALREADY_EXISTS]="Already_exists",
[error_codes.UNPREPARED]="Unprepared"
},
types = {
custom=0x00,
Expand Down
15 changes: 12 additions & 3 deletions src/cassandra/protocol.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ local constants = require("cassandra.constants")
local encoding = require("cassandra.encoding")
local decoding = require("cassandra.decoding")

local error_mt = {
local error_mt = {}
error_mt = {
__tostring = function(self)
return self.message
end,
__concat = function (a, b)
if getmetatable(a) == error_mt then
return a.message .. b
else
return a .. b.message
end
end
}

Expand All @@ -15,10 +23,11 @@ local function cassandra_error(message, code, raw_message)
end

local function read_error(buffer)
local error_code = constants.error_codes[decoding.read_int(buffer)]
local error_code = decoding.read_int(buffer)
local error_code_translation = constants.error_codes_translation[error_code]
local error_message = decoding.read_string(buffer)
return cassandra_error(
'Cassandra returned error (' .. error_code .. '): "' .. error_message .. '"',
'Cassandra returned error (' .. error_code_translation .. '): "' .. error_message .. '"',
error_code,
error_message
)
Expand Down

0 comments on commit 3002cbb

Please sign in to comment.