couchbase 1.2.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -1
- data/README.markdown +12 -8
- data/RELEASE_NOTES.markdown +19 -0
- data/couchbase.gemspec +1 -0
- data/examples/chat-goliath-grape/Gemfile +5 -0
- data/examples/chat-goliath-grape/README.markdown +50 -0
- data/examples/chat-goliath-grape/app.rb +67 -0
- data/examples/chat-goliath-grape/config/app.rb +20 -0
- data/examples/transcoders/Gemfile +3 -0
- data/examples/transcoders/README.markdown +59 -0
- data/examples/transcoders/cb-zcat +40 -0
- data/examples/transcoders/cb-zcp +45 -0
- data/examples/transcoders/gzip_transcoder.rb +49 -0
- data/examples/transcoders/options.rb +54 -0
- data/ext/couchbase_ext/arguments.c +67 -22
- data/ext/couchbase_ext/bucket.c +64 -20
- data/ext/couchbase_ext/context.c +2 -1
- data/ext/couchbase_ext/couchbase_ext.c +59 -9
- data/ext/couchbase_ext/couchbase_ext.h +18 -9
- data/ext/couchbase_ext/get.c +19 -23
- data/ext/couchbase_ext/store.c +1 -1
- data/ext/couchbase_ext/utils.c +38 -81
- data/lib/active_support/cache/couchbase_store.rb +60 -23
- data/lib/couchbase.rb +4 -2
- data/lib/couchbase/connection_pool.rb +55 -0
- data/lib/couchbase/transcoder.rb +120 -0
- data/lib/couchbase/version.rb +1 -1
- data/tasks/compile.rake +1 -1
- data/test/test_bucket.rb +1 -1
- data/test/test_couchbase_connection_pool.rb +73 -0
- data/test/test_couchbase_rails_cache_store.rb +36 -12
- data/test/test_format.rb +51 -1
- metadata +184 -127
- checksums.yaml +0 -15
@@ -97,7 +97,7 @@ struct cb_bucket_st
|
|
97
97
|
uint8_t connected; /* non-zero if instance has been connected. it is possible to defer connection with :async option */
|
98
98
|
uint8_t running; /* non-zero if event loop is running */
|
99
99
|
uint8_t trigger_connect_cb_on_set; /* if non-zero, the on_connect callback will be triggered immediately after set */
|
100
|
-
VALUE
|
100
|
+
VALUE transcoder;
|
101
101
|
uint32_t default_flags;
|
102
102
|
time_t default_ttl;
|
103
103
|
time_t default_observe_timeout;
|
@@ -127,7 +127,8 @@ struct cb_context_st
|
|
127
127
|
VALUE rv;
|
128
128
|
VALUE exception;
|
129
129
|
VALUE observe_options;
|
130
|
-
VALUE
|
130
|
+
VALUE transcoder;
|
131
|
+
VALUE transcoder_opts;
|
131
132
|
VALUE operation;
|
132
133
|
VALUE headers_val;
|
133
134
|
int headers_built;
|
@@ -169,8 +170,10 @@ extern VALUE cb_cTimer;
|
|
169
170
|
/* Modules */
|
170
171
|
extern VALUE cb_mCouchbase;
|
171
172
|
extern VALUE cb_mError;
|
173
|
+
extern VALUE cb_mTranscoder;
|
174
|
+
extern VALUE cb_mDocument;
|
175
|
+
extern VALUE cb_mPlain;
|
172
176
|
extern VALUE cb_mMarshal;
|
173
|
-
extern VALUE cb_mMultiJson;
|
174
177
|
extern VALUE cb_mURI;
|
175
178
|
extern VALUE em_m;
|
176
179
|
|
@@ -203,6 +206,7 @@ extern ID cb_sym_environment;
|
|
203
206
|
extern ID cb_sym_eventmachine;
|
204
207
|
extern ID cb_sym_extended;
|
205
208
|
extern ID cb_sym_flags;
|
209
|
+
extern ID cb_sym_forced;
|
206
210
|
extern ID cb_sym_format;
|
207
211
|
extern ID cb_sym_found;
|
208
212
|
extern ID cb_sym_get;
|
@@ -239,6 +243,7 @@ extern ID cb_sym_set;
|
|
239
243
|
extern ID cb_sym_stats;
|
240
244
|
extern ID cb_sym_timeout;
|
241
245
|
extern ID cb_sym_touch;
|
246
|
+
extern ID cb_sym_transcoder;
|
242
247
|
extern ID cb_sym_ttl;
|
243
248
|
extern ID cb_sym_type;
|
244
249
|
extern ID cb_sym_unlock;
|
@@ -336,10 +341,8 @@ int cb_first_value_i(VALUE key, VALUE value, VALUE arg);
|
|
336
341
|
void cb_build_headers(struct cb_context_st *ctx, const char * const *headers);
|
337
342
|
void cb_maybe_do_loop(struct cb_bucket_st *bucket);
|
338
343
|
VALUE cb_unify_key(struct cb_bucket_st *bucket, VALUE key, int apply_prefix);
|
339
|
-
VALUE cb_encode_value(VALUE val, uint32_t flags);
|
340
|
-
VALUE cb_decode_value(VALUE blob, uint32_t flags, VALUE
|
341
|
-
uint32_t cb_flags_set_format(uint32_t flags, ID format);
|
342
|
-
ID cb_flags_get_format(uint32_t flags);
|
344
|
+
VALUE cb_encode_value(VALUE transcoder, VALUE val, uint32_t *flags, VALUE options);
|
345
|
+
VALUE cb_decode_value(VALUE transcoder, VALUE blob, uint32_t flags, VALUE options);
|
343
346
|
void cb_async_error_notify(struct cb_bucket_st *bucket, VALUE exc);
|
344
347
|
|
345
348
|
|
@@ -388,6 +391,8 @@ VALUE cb_bucket_connected_p(VALUE self);
|
|
388
391
|
VALUE cb_bucket_async_p(VALUE self);
|
389
392
|
VALUE cb_bucket_quiet_get(VALUE self);
|
390
393
|
VALUE cb_bucket_quiet_set(VALUE self, VALUE val);
|
394
|
+
VALUE cb_bucket_transcoder_get(VALUE self);
|
395
|
+
VALUE cb_bucket_transcoder_set(VALUE self, VALUE val);
|
391
396
|
VALUE cb_bucket_default_flags_get(VALUE self);
|
392
397
|
VALUE cb_bucket_default_flags_set(VALUE self, VALUE val);
|
393
398
|
VALUE cb_bucket_default_format_get(VALUE self);
|
@@ -488,6 +493,8 @@ struct cb_params_st
|
|
488
493
|
lcb_cas_t cas;
|
489
494
|
lcb_datatype_t datatype;
|
490
495
|
VALUE observe;
|
496
|
+
VALUE transcoder;
|
497
|
+
VALUE transcoder_opts;
|
491
498
|
} store;
|
492
499
|
struct {
|
493
500
|
/* number of items */
|
@@ -509,7 +516,8 @@ struct cb_params_st
|
|
509
516
|
/* arguments given in form of hash key-ttl to "get and touch" */
|
510
517
|
unsigned int gat : 1;
|
511
518
|
lcb_time_t ttl;
|
512
|
-
VALUE
|
519
|
+
VALUE transcoder;
|
520
|
+
VALUE transcoder_opts;
|
513
521
|
VALUE keys_ary;
|
514
522
|
} get;
|
515
523
|
struct {
|
@@ -526,7 +534,8 @@ struct cb_params_st
|
|
526
534
|
lcb_uint64_t initial;
|
527
535
|
lcb_uint64_t delta;
|
528
536
|
int sign;
|
529
|
-
VALUE
|
537
|
+
VALUE transcoder;
|
538
|
+
VALUE transcoder_opts;
|
530
539
|
lcb_datatype_t datatype;
|
531
540
|
} arith;
|
532
541
|
struct {
|
data/ext/couchbase_ext/get.c
CHANGED
@@ -22,7 +22,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
22
22
|
{
|
23
23
|
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
24
|
struct cb_bucket_st *bucket = ctx->bucket;
|
25
|
-
VALUE key, val, flags, cas, exc = Qnil, res;
|
25
|
+
VALUE key, val, flags, cas, exc = Qnil, res, raw;
|
26
26
|
|
27
27
|
ctx->nqueries--;
|
28
28
|
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
@@ -38,22 +38,17 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
38
38
|
|
39
39
|
flags = ULONG2NUM(resp->v.v0.flags);
|
40
40
|
cas = ULL2NUM(resp->v.v0.cas);
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
|
53
|
-
val = raw;
|
54
|
-
}
|
55
|
-
} else if (cb_flags_get_format(resp->v.v0.flags) == cb_sym_plain) {
|
56
|
-
val = cb_vStrEmpty;
|
41
|
+
raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
|
42
|
+
val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts);
|
43
|
+
if (rb_obj_is_kind_of(val, rb_eStandardError)) {
|
44
|
+
VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
|
45
|
+
VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
|
46
|
+
rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str);
|
47
|
+
ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
|
48
|
+
rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
|
49
|
+
rb_ivar_set(ctx->exception, cb_id_iv_key, key);
|
50
|
+
rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
|
51
|
+
val = Qnil;
|
57
52
|
}
|
58
53
|
if (bucket->async) { /* asynchronous */
|
59
54
|
if (ctx->proc != Qnil) {
|
@@ -96,8 +91,8 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
96
91
|
* @param keys [String, Symbol, Array] One or several keys to fetch
|
97
92
|
* @param options [Hash] Options for operation.
|
98
93
|
* @option options [true, false] :extended (false) If set to +true+, the
|
99
|
-
* operation will return tuple +[value, flags, cas]+, otherwise (by
|
100
|
-
* default) it returns just value.
|
94
|
+
* operation will return a tuple +[value, flags, cas]+, otherwise (by
|
95
|
+
* default) it returns just the value.
|
101
96
|
* @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
102
97
|
* Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
103
98
|
* absolute times (from the epoch).
|
@@ -128,7 +123,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
128
123
|
* +cas+).
|
129
124
|
*
|
130
125
|
* @return [Object, Array, Hash] the value(s) (or tuples in extended mode)
|
131
|
-
*
|
126
|
+
* associated with the key.
|
132
127
|
*
|
133
128
|
* @raise [Couchbase::Error::NotFound] if the key is missing in the
|
134
129
|
* bucket.
|
@@ -137,7 +132,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
137
132
|
*
|
138
133
|
* @raise [ArgumentError] when passing the block in synchronous mode
|
139
134
|
*
|
140
|
-
* @example Get single value in
|
135
|
+
* @example Get single value in quiet mode (the default)
|
141
136
|
* c.get("foo") #=> the associated value or nil
|
142
137
|
*
|
143
138
|
* @example Use alternative hash-like syntax
|
@@ -199,7 +194,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
199
194
|
* @param options [Hash] Options for operation. (see options definition
|
200
195
|
* above)
|
201
196
|
*
|
202
|
-
* @return [Hash] the values (or tuples in extended mode)
|
197
|
+
* @return [Hash] the values (or tuples in extended mode) associated with
|
203
198
|
* the keys.
|
204
199
|
*
|
205
200
|
* @example Get and touch multiple keys
|
@@ -239,7 +234,8 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
|
|
239
234
|
ctx = cb_context_alloc_common(bucket, proc, params.cmd.get.num);
|
240
235
|
ctx->extended = params.cmd.get.extended;
|
241
236
|
ctx->quiet = params.cmd.get.quiet;
|
242
|
-
ctx->
|
237
|
+
ctx->transcoder = params.cmd.get.transcoder;
|
238
|
+
ctx->transcoder_opts = params.cmd.get.transcoder_opts;
|
243
239
|
if (params.cmd.get.replica) {
|
244
240
|
err = lcb_get_replica(bucket->handle, (const void *)ctx,
|
245
241
|
params.cmd.get.num, params.cmd.get.ptr_gr);
|
data/ext/couchbase_ext/store.c
CHANGED
@@ -201,7 +201,7 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
|
|
201
201
|
* @option options [Symbol] :format (self.default_format) The
|
202
202
|
* representation for storing the value in the bucket. For more info see
|
203
203
|
* {Bucket#default_format}.
|
204
|
-
* @option options [Fixnum] :cas The CAS value for an object. This value
|
204
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value is
|
205
205
|
* created on the server and is guaranteed to be unique for each value of
|
206
206
|
* a given key. This value is used to provide simple optimistic
|
207
207
|
* concurrency control when multiple clients or threads try to update an
|
data/ext/couchbase_ext/utils.c
CHANGED
@@ -360,89 +360,33 @@ cb_check_error(lcb_error_t rc, const char *msg, VALUE key)
|
|
360
360
|
return cb_check_error_with_status(rc, msg, key, 0);
|
361
361
|
}
|
362
362
|
|
363
|
-
|
364
|
-
uint32_t
|
365
|
-
cb_flags_set_format(uint32_t flags, ID format)
|
366
|
-
{
|
367
|
-
flags &= ~((uint32_t)CB_FMT_MASK); /* clear format bits */
|
368
|
-
|
369
|
-
if (format == cb_sym_document) {
|
370
|
-
return flags | CB_FMT_DOCUMENT;
|
371
|
-
} else if (format == cb_sym_marshal) {
|
372
|
-
return flags | CB_FMT_MARSHAL;
|
373
|
-
} else if (format == cb_sym_plain) {
|
374
|
-
return flags | CB_FMT_PLAIN;
|
375
|
-
}
|
376
|
-
return flags; /* document is the default */
|
377
|
-
}
|
378
|
-
|
379
|
-
ID
|
380
|
-
cb_flags_get_format(uint32_t flags)
|
381
|
-
{
|
382
|
-
flags &= CB_FMT_MASK; /* select format bits */
|
383
|
-
|
384
|
-
switch (flags) {
|
385
|
-
case CB_FMT_DOCUMENT:
|
386
|
-
return cb_sym_document;
|
387
|
-
case CB_FMT_MARSHAL:
|
388
|
-
return cb_sym_marshal;
|
389
|
-
case CB_FMT_PLAIN:
|
390
|
-
/* fall through */
|
391
|
-
default:
|
392
|
-
/* all other formats treated as plain */
|
393
|
-
return cb_sym_plain;
|
394
|
-
}
|
395
|
-
}
|
396
|
-
|
397
|
-
|
398
363
|
static VALUE
|
399
364
|
do_encode(VALUE *args)
|
400
365
|
{
|
401
366
|
VALUE val = args[0];
|
402
|
-
uint32_t flags = (
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
default:
|
412
|
-
/* all other formats treated as plain */
|
413
|
-
return val;
|
367
|
+
uint32_t *flags = (uint32_t *)args[1];
|
368
|
+
VALUE transcoder = args[2];
|
369
|
+
VALUE options = args[3];
|
370
|
+
VALUE ret;
|
371
|
+
|
372
|
+
ret = rb_funcall(transcoder, cb_id_dump, 3, val, ULONG2NUM(*flags), options);
|
373
|
+
Check_Type(ret, T_ARRAY);
|
374
|
+
if (RARRAY_LEN(ret) != 2) {
|
375
|
+
rb_raise(rb_eArgError, "#dump method of transcoder should return two items");
|
414
376
|
}
|
377
|
+
*flags = NUM2ULONG(RARRAY_PTR(ret)[1]);
|
378
|
+
return RARRAY_PTR(ret)[0];
|
415
379
|
}
|
416
380
|
|
417
381
|
static VALUE
|
418
382
|
do_decode(VALUE *args)
|
419
383
|
{
|
420
384
|
VALUE blob = args[0];
|
421
|
-
VALUE
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
} else if (force_format == cb_sym_marshal) {
|
427
|
-
return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
|
428
|
-
} else { /* cb_sym_plain and any other cb_symbol */
|
429
|
-
return blob;
|
430
|
-
}
|
431
|
-
} else {
|
432
|
-
uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
|
433
|
-
|
434
|
-
switch (flags) {
|
435
|
-
case CB_FMT_DOCUMENT:
|
436
|
-
return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
|
437
|
-
case CB_FMT_MARSHAL:
|
438
|
-
return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
|
439
|
-
case CB_FMT_PLAIN:
|
440
|
-
/* fall through */
|
441
|
-
default:
|
442
|
-
/* all other formats treated as plain */
|
443
|
-
return blob;
|
444
|
-
}
|
445
|
-
}
|
385
|
+
VALUE transcoder = args[2];
|
386
|
+
VALUE flags = args[1];
|
387
|
+
VALUE options = args[3];
|
388
|
+
|
389
|
+
return rb_funcall(transcoder, cb_id_load, 3, blob, ULONG2NUM(flags), options);
|
446
390
|
}
|
447
391
|
|
448
392
|
static VALUE
|
@@ -453,20 +397,27 @@ coding_failed(VALUE unused, VALUE exc)
|
|
453
397
|
}
|
454
398
|
|
455
399
|
VALUE
|
456
|
-
cb_encode_value(VALUE val, uint32_t flags)
|
400
|
+
cb_encode_value(VALUE transcoder, VALUE val, uint32_t *flags, VALUE options)
|
457
401
|
{
|
458
|
-
VALUE
|
402
|
+
VALUE args[4];
|
459
403
|
|
460
404
|
args[0] = val;
|
461
405
|
args[1] = (VALUE)flags;
|
462
|
-
|
463
|
-
|
406
|
+
args[2] = transcoder;
|
407
|
+
args[3] = options;
|
408
|
+
|
409
|
+
/* if nil, just pass value through */
|
410
|
+
if (NIL_P(args[2])) {
|
411
|
+
return val;
|
412
|
+
}
|
413
|
+
/* bytestring or exception object */
|
414
|
+
return rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
|
464
415
|
}
|
465
416
|
|
466
417
|
VALUE
|
467
|
-
cb_decode_value(VALUE blob, uint32_t flags, VALUE
|
418
|
+
cb_decode_value(VALUE transcoder, VALUE blob, uint32_t flags, VALUE options)
|
468
419
|
{
|
469
|
-
VALUE
|
420
|
+
VALUE args[4];
|
470
421
|
|
471
422
|
/* first it must be bytestring */
|
472
423
|
if (TYPE(blob) != T_STRING) {
|
@@ -474,9 +425,15 @@ cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format)
|
|
474
425
|
}
|
475
426
|
args[0] = blob;
|
476
427
|
args[1] = (VALUE)flags;
|
477
|
-
args[2] =
|
478
|
-
|
479
|
-
|
428
|
+
args[2] = transcoder;
|
429
|
+
args[3] = options;
|
430
|
+
|
431
|
+
/* if nil, just pass blob through */
|
432
|
+
if (NIL_P(args[2])) {
|
433
|
+
return blob;
|
434
|
+
}
|
435
|
+
/* the value or exception object */
|
436
|
+
return rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
|
480
437
|
}
|
481
438
|
|
482
439
|
void
|
@@ -55,9 +55,15 @@ module ActiveSupport
|
|
55
55
|
options[:default_ttl] ||= options.delete(:expires_in)
|
56
56
|
options[:default_format] ||= :marshal
|
57
57
|
options[:key_prefix] ||= options.delete(:namespace)
|
58
|
+
options[:connection_pool] ||= options.delete(:connection_pool)
|
58
59
|
args.push(options)
|
59
|
-
|
60
|
-
|
60
|
+
|
61
|
+
if options[:connection_pool]
|
62
|
+
@data = ::Couchbase::ConnectionPool.new(options[:connection_pool], *args)
|
63
|
+
else
|
64
|
+
@data = ::Couchbase::Bucket.new(*args)
|
65
|
+
@data.extend(Threadsafe)
|
66
|
+
end
|
61
67
|
end
|
62
68
|
|
63
69
|
# Fetches data from the cache, using the given key.
|
@@ -184,9 +190,7 @@ module ActiveSupport
|
|
184
190
|
options[:format] = :plain
|
185
191
|
end
|
186
192
|
instrument(:read_multi, names, options) do
|
187
|
-
@
|
188
|
-
@data.get(names, options)
|
189
|
-
end
|
193
|
+
@data.get(names, options)
|
190
194
|
end
|
191
195
|
rescue ::Couchbase::Error::Base => e
|
192
196
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -247,9 +251,7 @@ module ActiveSupport
|
|
247
251
|
options[:create] = true
|
248
252
|
instrument(:increment, name, options) do |payload|
|
249
253
|
payload[:amount] = amount if payload
|
250
|
-
@
|
251
|
-
@data.incr(name, amount, options)
|
252
|
-
end
|
254
|
+
@data.incr(name, amount, options)
|
253
255
|
end
|
254
256
|
rescue ::Couchbase::Error::Base => e
|
255
257
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -281,9 +283,7 @@ module ActiveSupport
|
|
281
283
|
options[:create] = true
|
282
284
|
instrument(:decrement, name, options) do |payload|
|
283
285
|
payload[:amount] = amount if payload
|
284
|
-
@
|
285
|
-
@data.decr(name, amount, options)
|
286
|
-
end
|
286
|
+
@data.decr(name, amount, options)
|
287
287
|
end
|
288
288
|
rescue ::Couchbase::Error::Base => e
|
289
289
|
logger.error("#{e.class}: #{e.message}") if logger
|
@@ -297,18 +297,14 @@ module ActiveSupport
|
|
297
297
|
#
|
298
298
|
# @return [Hash]
|
299
299
|
def stats(*arg)
|
300
|
-
@
|
301
|
-
@data.stats(*arg)
|
302
|
-
end
|
300
|
+
@data.stats(*arg)
|
303
301
|
end
|
304
302
|
|
305
303
|
protected
|
306
304
|
|
307
305
|
# Read an entry from the cache.
|
308
306
|
def read_entry(key, options) # :nodoc:
|
309
|
-
@
|
310
|
-
@data.get(key, options)
|
311
|
-
end
|
307
|
+
@data.get(key, options)
|
312
308
|
rescue ::Couchbase::Error::Base => e
|
313
309
|
logger.error("#{e.class}: #{e.message}") if logger
|
314
310
|
raise if @raise_errors
|
@@ -325,9 +321,7 @@ module ActiveSupport
|
|
325
321
|
if ttl = options.delete(:expires_in)
|
326
322
|
options[:ttl] ||= ttl
|
327
323
|
end
|
328
|
-
@
|
329
|
-
@data.send(method, key, value, options)
|
330
|
-
end
|
324
|
+
@data.send(method, key, value, options)
|
331
325
|
rescue ::Couchbase::Error::Base => e
|
332
326
|
logger.error("#{e.class}: #{e.message}") if logger
|
333
327
|
raise if @raise_errors
|
@@ -336,9 +330,7 @@ module ActiveSupport
|
|
336
330
|
|
337
331
|
# Delete an entry from the cache.
|
338
332
|
def delete_entry(key, options) # :nodoc:
|
339
|
-
@
|
340
|
-
@data.delete(key, options)
|
341
|
-
end
|
333
|
+
@data.delete(key, options)
|
342
334
|
rescue ::Couchbase::Error::Base => e
|
343
335
|
logger.error("#{e.class}: #{e.message}") if logger
|
344
336
|
raise if @raise_errors
|
@@ -367,6 +359,51 @@ module ActiveSupport
|
|
367
359
|
key.respond_to?(:to_param) ? key.to_param : key
|
368
360
|
end
|
369
361
|
|
362
|
+
module Threadsafe
|
363
|
+
def self.extended(obj)
|
364
|
+
obj.init_threadsafe
|
365
|
+
end
|
366
|
+
|
367
|
+
def get(*)
|
368
|
+
@lock.synchronize do
|
369
|
+
super
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
def send(*)
|
374
|
+
@lock.synchronize do
|
375
|
+
super
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def delete(*)
|
380
|
+
@lock.synchronize do
|
381
|
+
super
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def incr(*)
|
386
|
+
@lock.synchronize do
|
387
|
+
super
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def decr(*)
|
392
|
+
@lock.synchronize do
|
393
|
+
super
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def stats(*)
|
398
|
+
@lock.synchronize do
|
399
|
+
super
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def init_threadsafe
|
404
|
+
@lock = Monitor.new
|
405
|
+
end
|
406
|
+
end
|
370
407
|
end
|
371
408
|
end
|
372
409
|
end
|