The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Memorator::Backend - backend base class for Memorator

SYNOPSIS

   # meant to be used as a base class
   package Memorator::Backend::Whatever;
   use Mojo::Base 'Memorator::Backend';

   # this method is required, example taken from M::B::Mojo::Pg
   sub migration {
      my $self = shift;
      my $table = $self->table_name;
      return <<"END";
   -- 1 up
   CREATE TABLE IF NOT EXISTS $table (
      id     bigserial NOT NULL PRIMARY KEY,
      eid    text      NOT NULL,
      jid    bigint    NOT NULL,
      active int       NOT NULL DEFAULT 1
   );
   -- 1 down
   DROP TABLE $table;
   END
   }

   1;

DESCRIPTION

This is a base class for Memorator backends. A backend encapsulates all interactions with a database, most probably with a Mojo::* kind of database, like Mojo::Pg and Mojo::SQLite (which are supported directly by this distribution). As such, it is of interest only if you want to realize a new backend.

When you derive a class, you MUST either provide the migration method, or overload the "ensure_table" method. This will make sure that the needed mapping table is properly initialized in the database, with the correct name. The easiest way is to provide the migration method, to return a string with the migration, like in the following example for SQLite:

   sub migration {
      my $self = shift;
      my $table = $self->table_name;
      return <<"END";
   -- 1 up
   CREATE TABLE IF NOT EXISTS $table (
      id     INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
      eid    TEXT    NOT NULL,
      jid    INTEGER NOT NULL,
      active INTEGER NOT NULL DEFAULT 1
   );
   -- 1 down
   DROP TABLE $table;
   END
   }

A similar example for Postgresql can be found in the "SYNOPSIS". If a simple migration does not suffice, you can overload "ensure_table" and do whatever is needed to make sure that the table is present, with at least the four columns in the examples above.

Operations are performed against the database table whose name is provided by "table_name".

METHODS

The base class provides most of the methods that are needed by Memorator and you should not need to overload any... until you find out that you actually need to do so. Note that some methods have a _query counterpart, which lets you only provide the query and the list of binding parameters without overloading the whole method for making the call.

add_mapping

   $obj->add_mapping($eid, $jid);

add a mapping between external identifier $eid and the Minion job identifier $jid. Return value is ignored.

deactivate_mapping

   $obj->deactivate_mapping($id);

deactivate a mapping (identified by $id), i.e. sets the value of field active to 0. Return value is ignored.

deactivate_mapping_query

   my @query = $obj->deactivate_mapping_query($id);

provide a list of parameters suitable for a call to query() in the actual database backend. It is used by "deactivate_mapping". The default is:

   sub deactivate_mapping_query {
      my ($self, $id) = @_;
      my $table = $self->table_name;
      return ("UPDATE $table SET active = 0 WHERE id = ?", $id);
   }

ensure_table

   $obj->ensure_table;

ensure that the table for mapping job identifiers and external identifiers is present in the database. The default implementation leverages on the presence of method migration, which must be provided by the deriving class. See "DESCRIPTION" for additional details. Return value is ignored.

mapping_between

   my $e2j = $obj->mapping_between($eid, $jid);

find a mapping between an external identifier $eid and a job identifier $jid. Returns a hash with keys eid, jid, id (which is the identifier of the mapping itself, used e.g. in "deactivate_mapping" and "remove_mapping") and active.

Note that only valid mappings are returned, i.e. mappings that are active (according to the relevant field) and whose identifiers is the highest among all mappings with the specific external identifier eid.

Default implementation leverages on "mapping_between_query".

mapping_between_query

   my @query = $obj->mapping_between_query($eid, $jid);

query (with binding parameters) for finding the active, fresh mapping between an external identifier $eid and a job identifier $jid. The default implementation is the following:

   sub mapping_between_query {
      my ($self, $eid, $jid) = @_;
      my $table = $self->table_name;
      my $query =
         "SELECT * FROM $table "
      . " WHERE  jid = ? AND eid = ? AND active > 0 "
      . " AND id IN (SELECT MAX(id) FROM $table WHERE eid = ?)";
      return ($query, $jid, $eid, $eid);
   } ## end sub mapping_between_query

Note that the input identifiers are mapped multiple times in the binding parameters.

mojodb

   my $mdb = $obj->mojodb;
   $obj->mojodb($mojo_db_compatible);

accessor for a Mojo::Dbish object, like Mojo::Pg or Mojo::SQLite object. Mandatory. Can be set in the constructor via key mojodb.

name

   my $name = $obj->name;
   $obj->name($new_name);

accessor for a name for generating the local name of the table in the database, via "table_name". Mandatory. Can be set in the constructor via key name.

new

   my $obj = $classname>new(%args);
   my $obj = $classname>new(\%args);

constructor. The recognized keys in %args correspond to accessors "mojodb" (mandatory) and "name" (mandatory).

remove_mapping

   $obj->remove_mapping($id);

remove a mapping, identified by $id.

stale_mappings

   my @stale_hashrefs = $obj->stale_mappings;

find stale mappings and return them as hash references, each containing all fields for id, eid, jid and active. A stale mapping is a mapping that no longer applies, e.g. because a job has been superseded by another one for the specific external identifier eid. Stale mappings can be removed from the database.

The return value is a list of hash references, each having the keys above.

Leverages "stale_mappings_query".

stale_mappings_query

   my @query = $obj->stale_mappings_query;

return a query suitable for finding stale mappings, see "stale_mappings". The default implementation is the following:

   sub stale_mappings_query {
      my $self  = shift;
      my $table = $self->table_name;
      return
         "SELECT * FROM $table "
      . "  WHERE (id, eid) NOT IN "
      . "  (SELECT MAX(id), eid FROM $table GROUP BY eid)";
   } ## end sub stale_mappings_query

table_name

   my $table = $obj->table_name;

expand "TABLE_NAME" with "name" as a prefix, using "local_name" in Memorator::Util.

TABLE_NAME

   my $bare_table_name = $obj->TABLE_NAME;

the basic suffix for the table name, i.e. the constant eid2jid.

SEE ALSO

Memorator.

AUTHOR

Flavio Poletti <polettix@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2018 by Flavio Poletti <polettix@cpan.org>

This module is free software. You can redistribute it and/or modify it under the terms of the Artistic License 2.0.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.