datomic_gen_server v2.1.0 DatomicGenServer
DatomicGenServer is an Elixir GenServer that communicates with a Clojure Datomic peer running in the JVM, using clojure-erlastic.
The interface functions in this module communicate with Datomic using edn
strings. To use Elixir data structures, see the accompanying DatomicGenServer.db
module.
Examples
DatomicGenServer.start(
"datomic:mem://test",
true,
[{:timeout, 20_000}, {:default_message_timeout, 20_000}, {:name, DatomicGenServer}]
)
query = "[:find ?c :where [?c :db/doc \"Some docstring that isn't in the database\"]]"
DatomicGenServer.q(DatomicGenServer, query)
# => {:ok, "#{}\n"}
data_to_add = """
[ { :db/id #db/id[:db.part/db]
:db/ident :person/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc \"A person's name\"
:db.install/_attribute :db.part/db}]
"""
DatomicGenServer.transact(DatomicGenServer, data_to_add)
# => {:ok, "{:db-before {:basis-t 1000}, :db-after {:basis-t 1000},
:tx-data [{:a 50, :e 13194139534313, :v #inst \"2016-02-14T02:10:54.580-00:00\",
:tx 13194139534313, :added true} {:a 10, :e 64, :v :person/name, :tx 13194139534313,
:added true} {:a 40, :e 64, :v 23, :tx 13194139534313, :added true} {:a 41,
:e 64, :v 35, :tx 13194139534313, :added true} {:a 62, :e 64,
:v \"A person's name\", :tx 13194139534313, :added true} {:a 13,
:e 0, :v 64, :tx 13194139534313, :added true}], :tempids {-9223367638809264705 64}}"}
Summary
Functions
Issues an entity
call that is passed to the Datomic entity
API function
Issues a call to the Clojure net.phobot.datomic/seed library to load data into a database using data files in edn format. The database is not dropped, recreated, or migrated before loading
Issues a call to net.phobot.datomic/migrator to migrate a database using database migration files in edn format
Saves a snapshot of the current database state using a supplied key, and
creates a mock connection (using the datomock library) using that database
as a starting point. Requires the :allow_datomic_mocking?
configuration
parameter to be set in the :datomic_gen_server
application environment;
otherwise the current connection and database continue to be active.
Subsequent operations on the database will use the mock connection until
you call either the reset
or unmock
functions
Queries a DatomicGenServer using a query formulated as an edn string.
This query is passed to the Datomic q
API function
Generates a new mock connection using a database snapshot previously saved
using the mock
function. Requires the :allow_datomic_mocking?
configuration
parameter to be set in the :datomic_gen_server
application enviroment;
otherwise the current connection and database continue to be active
Starts the GenServer
Starts the GenServer in a linked process
Issues a transaction against a DatomicGenServer using a transaction
formulated as an edn string. This transaction is passed to the Datomic transact
API function
Reverts to using a database derived from the real database connection rather than a mocked connection. If no mock connection is active, this function is a no-op
Types
datomic_call :: {datomic_message, message_timeout :: non_neg_integer}
datomic_message ::
{:q, integer, String.t, [String.t]} |
{:transact, integer, String.t} |
{:entity, integer, String.t, [atom] | :all} |
{:migrate, integer, String.t} |
{:load, integer, String.t} |
{:mock, integer, atom} |
{:reset, integer, atom} |
{:unmock, integer}
datomic_result :: {:ok, String.t} | {:error, term}
send_option ::
{:message_timeout, non_neg_integer} |
{:client_timeout, non_neg_integer}
start_option ::
GenServer.option |
{:default_message_timeout, non_neg_integer}
Functions
Specs
entity(GenServer.server, String.t, [atom] | :all, [send_option]) :: datomic_result
Issues an entity
call that is passed to the Datomic entity
API function.
The first parameter to this function is the pid or alias of the GenServer process;
the second is an edn string representing the parameter that is to be passed to
entity
: either an entity id, an ident, or a lookup ref. The third parameter
is a list of atoms that represent the keys of the attributes you wish to fetch,
or :all
if you want all the entity’s attributes.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
DatomicGenServer.entity(DatomicGenServer, ":person/email", [:"db/valueType", :"db/doc"])
=> {:ok, "{:db/valueType :db.type/string, :db/doc \"A person's email\"}\n"}
Specs
load(GenServer.server, String.t, [send_option]) :: datomic_result
Issues a call to the Clojure net.phobot.datomic/seed library to load data into a database using data files in edn format. The database is not dropped, recreated, or migrated before loading.
The first parameter to this function is the pid or alias of the GenServer process; the second is the path to the directory containing the data files. The data files will be processed in the sort order of their directory.
Data is loaded in a single transaction. The return value of the function
is the result of the Datomic transact
API function call that executed the
transaction. If you want this result in a struct, call the wrapper load
function in the DatomicGenServer.Db
module.
Loading data does not use the Clojure Conformity library and is not idempotent.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
data_dir = Path.join [System.cwd(), "seed-data"]
DatomicGenServer.load(DatomicGenServer, data_dir)
=> {:ok, "{:db-before {:basis-t 1000}, :db-after {:basis-t 1000}, ...
Specs
migrate(GenServer.server, String.t, [send_option]) :: datomic_result
Issues a call to net.phobot.datomic/migrator to migrate a database using database migration files in edn format.
The first parameter to this function is the pid or alias of the GenServer process; the second is the path to the directory containing the migration files. Files will be processed in sort order. The Clojure Conformity library is used to keep the migrations idempotent.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
DatomicGenServer.migrate(DatomicGenServer, Path.join [System.cwd(), "migrations"])
=> {:ok, :migrated}
Specs
mock(GenServer.server, atom, [send_option]) :: datomic_result
Saves a snapshot of the current database state using a supplied key, and
creates a mock connection (using the datomock library) using that database
as a starting point. Requires the :allow_datomic_mocking?
configuration
parameter to be set in the :datomic_gen_server
application environment;
otherwise the current connection and database continue to be active.
Subsequent operations on the database will use the mock connection until
you call either the reset
or unmock
functions.
The first parameter to this function is the pid or alias of the GenServer process;
the second is the key under which to store the database snapshot. If successful,
the return value is a tuple of :ok
and the key that was passed to the function.
The active database can be reverted to the initial snapshot using the reset
function, or can be switched back to use the real, live connection and database
using the unmock
function.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
DatomicGenServer.mock(DatomicGenServer, :"just-migrated")
=> {:ok, :"just-migrated"}
Specs
q(GenServer.server, String.t, [String.t], [send_option]) :: datomic_result
Queries a DatomicGenServer using a query formulated as an edn string.
This query is passed to the Datomic q
API function.
The first parameter to this function is the pid or alias of the GenServer process; the second is the query.
The optional third parameter is a list of bindings for the data sources in the
query, passed to the inputs
argument of the Datomic q
function. IMPORTANT:
These bindings are passed in the form of edn strings which are read back in the
Clojure peer and then passed to Clojure eval
. Since any arbitrary Clojure forms
that are passed in are evaluated, you must be particularly careful that these
bindings are sanitized and that you are not passing anything that you don’t
control. In general, you should prefer the DatomicGenServer.Db.q/3
function
which accepts data structures and converts them to edn.
Bindings may include datomic_gen_server.peer/*db*
for the current database.
The options keyword list may include a :client_timeout
option that specifies the milliseconds timeout passed to GenServer.call, and a
:message_timeout
option that specifies how long the GenServer should wait
for a response before crashing (overriding the default value set in start
or
start_link
). Note that if the :client_timeout
is shorter than the
:message_timeout
value, the call will return an error but the server will
not crash even if the response message is never returned from the Clojure peer.
Example
query = "[:find ?c :where [?c :db/doc \"Some docstring that isn't in the database\"]]"
DatomicGenServer.q(DatomicGenServer, query)
=> {:ok, "#{}\n"}
Specs
reset(GenServer.server, atom, [send_option]) :: datomic_result
Generates a new mock connection using a database snapshot previously saved
using the mock
function. Requires the :allow_datomic_mocking?
configuration
parameter to be set in the :datomic_gen_server
application enviroment;
otherwise the current connection and database continue to be active.
The first parameter to this function is the pid or alias of the GenServer process;
the second is the key under which the database snapshot was saved. If successful,
the return value is a tuple of :ok
and the key that was passed to the function.
The database can be switched back to a real connection using the unmock
function. It is also possible to manipulate the mocked database and save that
new database state in a snapshot using the mock
function.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
DatomicGenServer.reset(DatomicGenServer, :"just-migrated")
=> {:ok, :"just-migrated"}
Specs
start(String.t, boolean, [start_option]) :: GenServer.on_start
Starts the GenServer.
This function is basically a pass-through to GenServer.start
, but with some
additional parameters: The first is the URL of the Datomic transactor to which
to connect, and the second a boolean parameter indicating whether or not to
create the database if it does not yet exist.
The options keyword list may include the normal options accepted by GenServer.start
,
as well as a :default_message_timeout
option that controls the default time in
milliseconds that the server will wait for a message before crashing. Note that
if the :timeout
option is provided, the GenServer will crash if that timeout
is exceeded.
Example
DatomicGenServer.start(
"datomic:mem://test",
true,
[{:timeout, 20_000}, {:default_message_timeout, 20_000}, {:name, DatomicGenServer}]
)
Specs
start_link(String.t, boolean, [start_option]) :: GenServer.on_start
Starts the GenServer in a linked process.
This function is basically a pass-through to GenServer.start_link
, but with
some additional parameters: The first is the URL of the Datomic transactor to
which to connect, and the second a boolean parameter indicating whether or not
to create the database if it does not yet exist.
The options keyword list may include the normal options accepted by GenServer.start_link
,
as well as a :default_message_timeout
option that controls the default time in
milliseconds that the server will wait for a message before crashing. Note that
if the :timeout
option is provided, the GenServer will crash if that timeout
is exceeded.
Example
DatomicGenServer.start_link(
"datomic:mem://test",
true,
[{:timeout, 20_000}, {:default_message_timeout, 20_000}, {:name, DatomicGenServer}]
)
Specs
transact(GenServer.server, String.t, [send_option]) :: datomic_result
Issues a transaction against a DatomicGenServer using a transaction
formulated as an edn string. This transaction is passed to the Datomic transact
API function.
The first parameter to this function is the pid or alias of the GenServer process;
the second is the transaction data in edn format. The options keyword list may
include a :client_timeout
option that specifies the milliseconds timeout passed
to GenServer.call, and a :message_timeout
option that specifies how long the
GenServer should wait for a response before crashing (overriding the default
value set in start
or start_link
). Note that if the :client_timeout
is
shorter than the :message_timeout
value, the call will return an error but
the server will not crash even if the response message is never returned from
the Clojure peer.
Example
data_to_add = """
[ { :db/id #db/id[:db.part/db]
:db/ident :person/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc \"A person's name\"
:db.install/_attribute :db.part/db}]
"""
DatomicGenServer.transact(DatomicGenServer, data_to_add)
=> {:ok, "{:db-before {:basis-t 1000}, :db-after {:basis-t 1000},
:tx-data [{:a 50, :e 13194139534313, :v #inst \"2016-02-14T02:10:54.580-00:00\",
:tx 13194139534313, :added true} {:a 10, :e 64, :v :person/name, :tx 13194139534313,
:added true} {:a 40, :e 64, :v 23, :tx 13194139534313, :added true} {:a 41,
:e 64, :v 35, :tx 13194139534313, :added true} {:a 62, :e 64,
:v \"A person's name\", :tx 13194139534313, :added true} {:a 13,
:e 0, :v 64, :tx 13194139534313, :added true}], :tempids {-9223367638809264705 64}}"}
Specs
unmock(GenServer.server, [send_option]) :: datomic_result
Reverts to using a database derived from the real database connection rather than a mocked connection. If no mock connection is active, this function is a no-op.
If the call is successful, the return value is a tuple of :ok
and :unmocked
.
The first parameter to this function is the pid or alias of the GenServer process.
The options keyword list may include a :client_timeout
option that specifies
the milliseconds timeout passed to GenServer.call, and a :message_timeout
option that specifies how long the GenServer should wait for a response before
crashing (overriding the default value set in start
or start_link
). Note
that if the :client_timeout
is shorter than the :message_timeout
value,
the call will return an error but the server will not crash even if the message
is never returned from the Clojure peer.
Example
DatomicGenServer.unmock(DatomicGenServer)
=> {:ok, :unmocked}