our
$VERSION
=
'0.94'
;
__PACKAGE__->mk_classdata(
'_session_cb_bucket_handle'
);
__PACKAGE__->mk_classdata(
'_session_couchbase_prefix'
);
sub
setup_session {
my
$c
=
shift
;
$c
->maybe::
next
::method(
@_
);
$c
->
log
->debug(
"Setting up Couchbase session store"
)
if
$c
->debug;
my
$session_cfg
=
$c
->config->{
'Plugin::Session'
};
if
(
$c
->config->{Couchbase} and not
$session_cfg
->{couchbase_server} ) {
foreach
my
$k
(
keys
%{
$c
->config->{Couchbase}} ) {
$session_cfg
->{
'couchbase_'
.
$k
} =
$c
->config->{Couchbase}->{
$k
};
}
}
my
$cfg
= {
map
{
my
$k
=
$_
;
$k
=~ s/^couchbase_//;
$k
=>
$session_cfg
->{
$_
} }
keys
%{
$session_cfg
}
};
my
$appname
=
"$c"
;
$c
->_session_couchbase_prefix(
$appname
.
"sess:"
);
my
$connection_url
= _build_couchbase_url(
$cfg
);
my
$bucket
= Couchbase::Bucket->new(
$connection_url
);
Catalyst::Exception->throw(
"Couchbase bucket object undefined!"
)
unless
defined
$bucket
;
$c
->_session_cb_bucket_handle(
$bucket
);
return
1;
}
sub
get_session_data {
my
(
$c
,
$key
) =
@_
;
croak(
"No cache key specified"
)
unless
length
(
$key
);
my
(
$type
,
$id
) =
split
(
':'
,
$key
);
$key
=
$c
->_session_couchbase_prefix .
$id
;
my
$doc
= Couchbase::Document->new(
$key
);
$c
->_session_cb_bucket_handle->get_and_touch(
$doc
);
if
(
defined
$doc
and
$doc
->is_ok and
defined
$doc
->value) {
return
$doc
->value->{
$type
};
}
elsif
(
defined
$doc
) {
my
$err
=
$doc
->errstr;
Catalyst::Exception->throw(
"Failed to fetch Couchbase item: $err. Key was: $key"
)
unless
$err
=~ /key does not exist/;
}
return
;
}
sub
store_session_data {
my
(
$c
,
$key
,
$data
) =
@_
;
croak(
"No cache key specified"
)
unless
length
(
$key
);
my
(
$type
,
$id
) =
split
(
':'
,
$key
);
$key
=
$c
->_session_couchbase_prefix .
$id
;
my
$expiry
=
$c
->session_expires ?
$c
->session_expires -
time
() : 0;
if
(not
$expiry
) {
$c
->
log
->
warn
(
"No expiry set for sessions! Defaulting to one hour.."
);
$expiry
= 3600;
}
my
$doc
= Couchbase::Document->new(
$key
);
$c
->_session_cb_bucket_handle->get(
$doc
);
if
(
$doc
->is_ok) {
$doc
->value->{
$type
} =
$data
;
$doc
->expiry(
$expiry
);
$c
->_session_cb_bucket_handle->replace(
$doc
);
}
else
{
$doc
= Couchbase::Document->new(
$key
, {} );
$doc
->value->{
$type
} =
$data
;
$doc
->expiry(
$expiry
);
$c
->_session_cb_bucket_handle->insert(
$doc
);
}
unless
(
$doc
->is_ok) {
Catalyst::Exception->throw(
"Couldn't save $key / $data in couchbase storage: "
.
$doc
->errstr
);
}
return
1;
}
sub
delete_session_data {
my
(
$c
,
$key
) =
@_
;
$c
->
log
->debug(
"Couchbase session store: delete_session_data($key)"
)
if
$c
->debug;
croak(
"No cache key specified"
)
unless
length
(
$key
);
my
(
$type
,
$id
) =
split
(
':'
,
$key
);
$key
=
$c
->_session_couchbase_prefix .
$id
;
my
$doc
= Couchbase::Document->new(
$key
);
$c
->_session_cb_bucket_handle->remove(
$doc
);
return
1;
}
sub
delete_expired_sessions { }
sub
_build_couchbase_url {
my
(
$cfg
) =
@_
;
my
%options
= (
config_node_timeout
=> (
$cfg
->{timeout} or 6 ) * 1_000_000,
);
Catalyst::Exception->throw(
'Missing Couchbase server'
)
unless
$cfg
->{server};
my
$connection_url
=
join
(
'/'
,
':/'
,
$cfg
->{server},
(
$cfg
->{bucket} or
'default'
),
);
$options
{password} =
$cfg
->{password}
if
(
$cfg
->{password});
if
(
$cfg
->{ssl}) {
if
(not
$cfg
->{certpath} or not -e
$cfg
->{certpath}) {
Catalyst::Exception->throw(
'SSL enabled, but certpath is missing or invalid'
);
}
$connection_url
=
'couchbases'
.
$connection_url
;
$options
{certpath} =
$cfg
->{certpath};
}
else
{
$connection_url
=
'couchbase'
.
$connection_url
;
}
$connection_url
.=
'?'
.
join
(
'&'
, (
map
{
$_
.
'='
. uri_escape(
$options
{
$_
}) }
keys
%options
)
);
return
$connection_url
;
}
__PACKAGE__->meta->make_immutable;
1;