including: + call_id + start_time + duration + caller (from_uri) + callee (to_uri) Change-Id: I1b0aea9bf578a71fd3e1a5433c9801ebde173b65changes/39/20039/9
parent
13cc8b6f66
commit
fefcaef806
@ -0,0 +1,61 @@
|
||||
package NGCP::Panel::Controller::API::CallQueues;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use boolean qw(true);
|
||||
use Data::HAL qw();
|
||||
use Data::HAL::Link qw();
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD/];
|
||||
}
|
||||
|
||||
sub api_description {
|
||||
return 'The queue of waiting calls per subscriber.';
|
||||
};
|
||||
|
||||
sub query_params {
|
||||
return [
|
||||
{
|
||||
param => 'reseller_id',
|
||||
description => 'Filter for callqueues of subscribers belonging to a specific reseller',
|
||||
query => {
|
||||
first => sub {
|
||||
my $q = shift;
|
||||
{ 'domain_resellers.reseller_id' => $q };
|
||||
},
|
||||
second => sub {
|
||||
{ join => 'domain_resellers' };
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
# we handle that separately/manually in the role
|
||||
param => 'number',
|
||||
description => 'Filter for callqueues of subscribers with numbers matching the given pattern.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::CallQueues/;
|
||||
|
||||
sub resource_name{
|
||||
return 'callqueues';
|
||||
}
|
||||
|
||||
sub dispatch_path{
|
||||
return '/api/callqueues/';
|
||||
}
|
||||
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-callqueues';
|
||||
}
|
||||
|
||||
__PACKAGE__->set_config({
|
||||
allowed_roles => [qw/admin reseller subscriberadmin subscriber/],
|
||||
});
|
||||
|
||||
1;
|
@ -0,0 +1,35 @@
|
||||
package NGCP::Panel::Controller::API::CallQueuesItem;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
require Catalyst::ActionRole::ACL;
|
||||
require NGCP::Panel::Role::HTTPMethods;
|
||||
require Catalyst::ActionRole::RequireSSL;
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD/];
|
||||
}
|
||||
|
||||
use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::CallQueues/;
|
||||
|
||||
sub resource_name{
|
||||
return 'callqueues';
|
||||
}
|
||||
|
||||
sub dispatch_path{
|
||||
return '/api/callqueues/';
|
||||
}
|
||||
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-callqueues';
|
||||
}
|
||||
|
||||
__PACKAGE__->set_config({
|
||||
allowed_roles => [qw/admin reseller subscriberadmin subscriber/],
|
||||
});
|
||||
|
||||
1;
|
@ -0,0 +1,32 @@
|
||||
package NGCP::Panel::Form::CallQueue::API;
|
||||
use HTML::FormHandler::Moose;
|
||||
extends 'HTML::FormHandler';
|
||||
|
||||
has_field 'id' => (
|
||||
type => 'Hidden',
|
||||
noupdate => 1,
|
||||
);
|
||||
|
||||
has_field 'queue_length' => (
|
||||
type => 'Integer',
|
||||
required => 0,
|
||||
default => '0',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['The length of the call queue.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'queue' => (
|
||||
type => 'Repeatable',
|
||||
do_wrapper => 1,
|
||||
do_label => 0,
|
||||
required => 0,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Number of Objects, each containing the keys ' .
|
||||
'"start_time", "duration", "callee" and "caller".'],
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
@ -0,0 +1,200 @@
|
||||
package NGCP::Panel::Role::API::CallQueues;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use parent 'NGCP::Panel::Role::API';
|
||||
|
||||
use boolean qw(true);
|
||||
use Data::HAL qw();
|
||||
use Data::HAL::Link qw();
|
||||
|
||||
my $redis_callqueue_key_prefix = 'callqueue:';
|
||||
my $redis_dialogdata_key_prefix = 'dialog:cid::';
|
||||
my $number_search_limit = 100; # scan redis only if collection gets bigger than this
|
||||
|
||||
# todo: move this stash factory method below to some util.
|
||||
sub _get_redis {
|
||||
my ($self, $c, $select) = @_;
|
||||
my $stash_key = 'redis';
|
||||
if (defined $select) {
|
||||
$stash_key .= '_' . $select;
|
||||
} else {
|
||||
$c->log->error("redis store not specified");
|
||||
return;
|
||||
}
|
||||
my $redis = $c->stash->{$stash_key};
|
||||
unless ($redis) {
|
||||
try {
|
||||
$redis = Redis->new(
|
||||
server => $c->config->{redis}->{central_url},
|
||||
reconnect => 10, every => 500000, # 500ms
|
||||
cnx_timeout => 3,
|
||||
);
|
||||
unless ($redis) {
|
||||
$c->log->error("Failed to connect to central redis url " . $c->config->{redis}->{central_url});
|
||||
return;
|
||||
}
|
||||
$redis->select($select) if defined $select;
|
||||
$c->stash($stash_key => $redis);
|
||||
} catch($e) {
|
||||
$c->log->error("Failed to fetch callqueue information from redis: $e");
|
||||
return;
|
||||
}
|
||||
}
|
||||
return $redis;
|
||||
}
|
||||
|
||||
sub _item_rs {
|
||||
my ($self, $c, $id) = @_;
|
||||
|
||||
#$c->config->{redis}->{callqueue_db} = 3;
|
||||
my $redis = $self->_get_redis($c,$c->config->{redis}->{callqueue_db});
|
||||
|
||||
my $rs = $c->model('DB')->resultset('voip_subscribers');
|
||||
if($c->user->roles eq "admin") {
|
||||
} elsif($c->user->roles eq "reseller") {
|
||||
$rs = $rs->search_rs({
|
||||
'contact.reseller_id' => $c->user->reseller_id,
|
||||
},{
|
||||
join => { 'contract' => 'contact' }
|
||||
});
|
||||
} elsif ($c->user->roles eq "subscriberadmin") {
|
||||
$rs = $rs->search_rs({
|
||||
'me.contract_id' => $c->user->account_id,
|
||||
});
|
||||
} elsif ($c->user->roles eq "subscriber") {
|
||||
$rs = $rs->search_rs({
|
||||
'me.uuid' => $c->user->uuid,
|
||||
});
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
my $subs = $rs->find($id);
|
||||
if ($subs) {
|
||||
$rs = $rs->search_rs({
|
||||
'me.uuid' => ($redis->exists($redis_callqueue_key_prefix . $subs->uuid) ? $subs->uuid : -1),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
my $callqueue_uuids = $c->stash->{callqueue_uuids};
|
||||
if ($c->req->params->{number}) {
|
||||
$rs = $rs->search_rs({
|
||||
'voip_dbaliases.username' => { like => $c->req->params->{number} },
|
||||
},{
|
||||
join => { 'provisioning_voip_subscriber' => 'voip_dbaliases' },
|
||||
distinct => 1,
|
||||
});
|
||||
if (not $callqueue_uuids and $rs->search_rs(undef,{ rows => $number_search_limit, })->count < $number_search_limit) {
|
||||
$callqueue_uuids = [ -1 ];
|
||||
for my $subs ($rs->all) {
|
||||
push(@$callqueue_uuids,$subs->uuid) if $redis->exists($redis_callqueue_key_prefix . $subs->uuid);
|
||||
}
|
||||
$c->stash(callqueue_uuids => $callqueue_uuids);
|
||||
}
|
||||
}
|
||||
unless ($callqueue_uuids) {
|
||||
$callqueue_uuids = [ -1 ];
|
||||
my $cursor = 0;
|
||||
do {
|
||||
my $res = $redis->scan($cursor, MATCH => $redis_callqueue_key_prefix . '*', COUNT => 1000);
|
||||
$cursor = shift @$res;
|
||||
my $mapkeys = shift @$res;
|
||||
foreach my $mapkey (@$mapkeys) {
|
||||
push(@$callqueue_uuids,$mapkey =~ s/^$redis_callqueue_key_prefix//r);
|
||||
}
|
||||
} while ($cursor);
|
||||
$c->stash(callqueue_uuids => $callqueue_uuids);
|
||||
}
|
||||
$rs = $rs->search_rs({
|
||||
'me.uuid' => { -in => $callqueue_uuids },
|
||||
});
|
||||
}
|
||||
|
||||
return $rs;
|
||||
}
|
||||
|
||||
sub get_form {
|
||||
my ($self, $c) = @_;
|
||||
return NGCP::Panel::Form::get("NGCP::Panel::Form::CallQueue::API", $c);
|
||||
}
|
||||
|
||||
sub hal_links {
|
||||
my($self, $c, $item, $resource, $form) = @_;
|
||||
return [
|
||||
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
|
||||
];
|
||||
}
|
||||
|
||||
sub hal_from_item {
|
||||
my ($self, $c, $item, $form) = @_;
|
||||
|
||||
my $hal = Data::HAL->new(
|
||||
links => [
|
||||
Data::HAL::Link->new(
|
||||
relation => 'curies',
|
||||
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
|
||||
name => 'ngcp',
|
||||
templated => true,
|
||||
),
|
||||
Data::HAL::Link->new(relation => 'collection', href => sprintf("/api/%s/", $self->resource_name)),
|
||||
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
|
||||
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%d", $self->dispatch_path, $item->id)),
|
||||
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
|
||||
],
|
||||
relation => 'ngcp:'.$self->resource_name,
|
||||
);
|
||||
|
||||
my $resource = $self->resource_from_item($c, $item, $form);
|
||||
$hal->resource($resource);
|
||||
return $hal;
|
||||
}
|
||||
|
||||
sub resource_from_item {
|
||||
my ($self, $c, $item, $form) = @_;
|
||||
|
||||
my %resource = ();
|
||||
|
||||
#$c->config->{redis}->{callqueue_db} = 3;
|
||||
#$c->config->{redis}->{dialog_db} = 23;
|
||||
|
||||
my $redis = $self->_get_redis($c,$c->config->{redis}->{callqueue_db});
|
||||
my $res = $redis->lrange($redis_callqueue_key_prefix . $item->uuid, 0, -1);
|
||||
$redis = $self->_get_redis($c,$c->config->{redis}->{dialog_db});
|
||||
my @callqueue = ();
|
||||
if ($res) {
|
||||
foreach my $call_id (@$res) {
|
||||
my $queue_item = {
|
||||
duration => undef,
|
||||
caller => undef,
|
||||
callee => undef,
|
||||
start_time => undef,
|
||||
call_id => $call_id,
|
||||
};
|
||||
my $dialogentry_keys = $redis->smembers($redis_dialogdata_key_prefix . $call_id);
|
||||
#use Data::Dumper;
|
||||
#$c->log->debug($redis_dialogdata_key_prefix . $call_id . ' -> ' . Dumper($dialogentry_keys));
|
||||
if ($dialogentry_keys) {
|
||||
foreach my $dialogentry_key (@$dialogentry_keys) {
|
||||
my %dialogdata = $redis->hgetall($dialogentry_key);
|
||||
if ($dialogdata{start_time}) {
|
||||
my $duration = time() - $dialogdata{start_time};
|
||||
if (not defined $queue_item->{start_time} or $dialogdata{start_time} < $queue_item->{duration}) {
|
||||
$queue_item->{duration} = time() - $dialogdata{start_time};
|
||||
$queue_item->{caller} = $dialogdata{from_uri};
|
||||
$queue_item->{start_time} = $dialogdata{start_time};
|
||||
$queue_item->{callee} = $dialogdata{to_uri};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
push(@callqueue,$queue_item);
|
||||
}
|
||||
}
|
||||
$resource{queue} = \@callqueue;
|
||||
$resource{queue_length} = scalar @callqueue;
|
||||
|
||||
return \%resource;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in new issue