Skip to content

Commit

Permalink
Drafted SQLite backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Henning Thorsen committed Aug 25, 2021
1 parent 3771da3 commit 6c7ff3d
Showing 1 changed file with 253 additions and 0 deletions.
253 changes: 253 additions & 0 deletions lib/Convos/Core/Backend/SQLite.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
package Convos::Core::Backend::SQLite;
use Mojo::Base 'Convos::Core::Backend';

use Mojo::SQLite;
use Convos::Date qw(dt);
use Mojo::JSON qw(false true);

has home => sub { Carp::confess('home() cannot be built') };
has sqlite => sub { Mojo::SQLite->new('sqlite:' . shift->home->child('convos.sqlite')) };

sub connections_p {
my ($self, $user) = @_;

return $self->sqlite->db->select_p('convos_connections')->then(sub {
return shift->hashes->to_array;
});
}

sub delete_messages_p {
my ($self, $obj) = @_;
return Mojo::Promise->reject('Unknown target.') unless $obj and $obj->connection;
return $self->sqlite->db->delete_p(convos_messages => {conversation_id => $obj->id})
->then(sub {$obj});
}

sub delete_object_p {
my ($self, $obj) = @_;

if ($obj->isa('Convos::Core::Connection')) {
$obj->unsubscribe($_) for qw(conversation message state);
}

return $self->delete_p($self->_obj_to_table($obj), {id => $obj->id})->then(sub {$obj});
}

sub load_object_p {
my ($self, $obj) = @_;

return $self->select_p($self->_obj_to_table($obj), {id => $obj->id})->then(sub {
return shift->hash;
});
}

sub messages_p {
my ($self, $obj, $query) = @_;

if ($query->{around}) {
my %query_before = (%$query, around => undef, before => $query->{around});
my %query_after = (%$query, around => undef, after => $query->{around}, include => 1);

return Mojo::Promise->all(
$self->messages_p($obj, \%query_before),
$self->messages_p($obj, \%query_after),
)->then(sub {
my ($before, $after) = map { $_->[0] } @_;
return {%$before, %$after, messages => [map { @{$_->{messages}} } ($before, $after)]};
});
}

my %extra = (limit => $query->{limit} || 60);
$extra{order_by} = {-desc => 'ts'};

my %where = (id => $obj->id);
$where{from} = $query->{from} if $query->{from};

my $lt = $query->{include} ? '<=' : '<';
my $gt = $query->{include} ? '>=' : '>';
push @{$where{ts}}, {$gt => dt $query->{after}} if $query->{after};
push @{$where{ts}}, {$lt => dt $query->{before}} if $query->{before};

return $self->select_p(convos_messages => \%where, \%extra)->then(sub {
return shift->hashes->to_array;
});
}

sub notifications_p {
my ($self, $user, $query) = @_;

my %extra = (limit => $query->{limit} || 60);
$extra{order_by} = {-desc => 'ts'};

return $self->select_p(convos_notifications => {}, \%extra)->then(sub {
return shift->hashes->to_array;
});
}

sub save_object_p {
my ($self, $obj) = @_;

return $self->insert_p($self->_obj_to_table($obj), $obj->TO_JSON('private'))->then(sub {$obj});
}

sub users_p {
my $self = shift;

return $self->sqlite->db->select_p('convos_users')->then(sub {
return shift->hashes->sort(sub {
$a->{registered} cmp $b->{registered} || $a->{email} cmp $b->{email};
})->to_array;
});
}

sub _add_notification_p {
my ($self, $target, $msg) = @_;

return $self->sqlite->db->insert_p(
convos_notifications => {
connection_id => $target->connection->id,
conversation_id => $target->id,
from => $msg->{from},
message => $msg->{message},
ts => dt($msg->{ts})->to_datetime,
type => $msg->{type} || 'normal',
}
);
}

sub _log_p {
my ($self, $target, $msg) = @_;

return $self->sqlite->db->insert_p(
convos_notifications => {
connection_id => $target->connection->id,
conversation_id => $target->id,
from => $msg->{from},
highlight => $msg->{highlight} ? 1 : 0,
message => $msg->{message},
ts => dt($msg->{ts})->to_datetime,
type => $msg->{type} || 'normal',
}
);
}

sub _obj_to_table {
my ($self, $obj) = @_;
return 'convos_connections' if $obj->isa('Convos::Core::Connection');
return 'convos_conversations' if $obj->isa('Convos::Core::Conversation');
return 'convos_settings' if $obj->isa('Convos::Core::Settings');
return 'convos_users' if $obj->isa('Convos::Core::User');
return 'convos_unknown_object';
}

sub _setup {
my $self = shift;

Scalar::Util::weaken($self);
my $catch = sub { $self->emit(error => shift) };

$self->on(
connection => sub {
my ($self, $connection) = @_;
my $cid = $connection->id;
my $uid = $connection->user->id;

Scalar::Util::weaken($self);
$connection->on(
message => sub {
my ($connection, $target, $msg) = @_;

if ($msg->{highlight} and $target->id and !$target->is_private) {
$self->_add_notification_p($target, $msg)->catch($catch);
$connection->user->save_p->catch($catch);
}

$self->_log_p($target, $msg)->catch($catch);
}
);
}
);

return $self->SUPER::_setup;
}

1;

=encoding utf8
=head1 NAME
Convos::Core::Backend::SQLite - Backend for storing objects to SQLite
=head1 DESCRIPTION
L<Convos::Core::Backend::SQLite> contains methods which is useful for objects
that want to be persisted to an SQLite database.
=head2 Where is data stored
C<CONVOS_HOME> can be set to specify the root location for where to save store
the SQLite database. The default directory on *nix systems is something like
this:
$HOME/.local/share/convos/
C<$HOME> is figured out from L<File::HomeDir/my_home>.
=head1 ATTRIBUTES
L<Convos::Core::Backend::File> inherits all attributes from
L<Convos::Core::Backend> and implements the following new ones.
=head2 home
See L<Convos::Core/home>.
=head2 sqlite
$sqlite = $backend->sqlite;
Returns a L<Mojo::SQLite> object.
=head1 METHODS
L<Convos::Core::Backend::File> inherits all methods from
L<Convos::Core::Backend> and implements the following new ones.
=head2 connections_p
See L<Convos::Core::Backend/connections_p>.
=head2 delete_messages_p
See L<Convos::Core::Backend/delete_messages_p>.
=head2 delete_object_p
See L<Convos::Core::Backend/delete_object_p>.
=head2 load_object_p
See L<Convos::Core::Backend/load_object_p>.
=head2 messages_p
See L<Convos::Core::Backend/messages_p>.
=head2 notifications_p
See L<Convos::Core::Backend/notifications_p>.
=head2 save_object_p
See L<Convos::Core::Backend/save_object_p>.
=head2 users_p
See L<Convos::Core::Backend/users_p>.
=head1 SEE ALSO
L<Convos::Core>.
=cut

0 comments on commit 6c7ff3d

Please sign in to comment.