Services as Databases pattern
svc_expr
services can function as databases, which can be updated or
queried by operations on them.
A database is defined as a state variable on the service. Operations on the service can read from this database or update it.
Such a state variable can be any Erlang term. For example, an Erlang map or list.
The expr.init.[Var]
property can be used to define an initial map. If the
state is updated, a new map is returned.
Table 1 shows an example using a service as a database.
The list below shows sample database constructions.
-
- Records (Erlang map)
-
#{0 => "foo", 1 => "bar"}
-
- Records with keys (Maps within a map)
-
#{ 0 => #{ key => 0, first_name => "Bill", last_name => "Door"}, 1 => #{ key => 1, first_name => "King", last_name => "Kong"} }
-
- Listed records (List of maps)
-
[ #{ name => "Bob", dob => {1976,10,18}, gender => male}, #{ name => "Mary", dob => {1999,11,07}, gender => female} ]
Example | Description |
---|---|
<service name="Database" provision="expr"> <prop name="expr.state" Table="NewTable" NextID="NewNextID"/> <prop name="expr.init.Table" content-type="text/x-erlang"><![CDATA[ #{0 => "foo", 1 => "bar"} ]]></prop> <prop name="expr.init" NextID="2"/> </service> |
The Database service is provisioned using the Expressions
extension.The following state variables are specified for
Note: Variable names must start with a capital letter.
The
Important: Do not use a full stop at the end of the term, like in
the case of expressions contained in
The records have an ID, a key in other words, and a value.expr.src .The
|
<request name="Insert" service="Database" fields="INSERT name"> <prop name="expr.src" content-type="text/x-erlang"><![CDATA[ Name = get("name"), NewTable = Table#{ NextID => Name}, put("id", NextID), NewNextID = NextID + 1, "Ok". ]]></prop> <reply name="Ok" fields="id"/> </request> |
The Insert operation updates the Table
variable, and thus creates a new map. The new map contains:
The input and output fields of The expressions
in
The Note: Do not manually type the
<![CDATA...]]> delimiters. The Editor
automatically renders text content as XML CDATA sections. |
<request name="Get" service="Database" fields="GET id"> <prop name="expr.src" content-type="text/x-erlang"><![CDATA[ Id = get("id"), case maps:is_key(Id, Table) of true -> Name = maps:get(Id, Table), put("name", Name), "Ok"; false -> put("error", not_found), "Error" end. ]]></prop> <reply name="Ok" fields="name"/> <reply name="Error" fields="error"/> </request> |
The Get operation returns a record based on its key, if the key
matches any record.The key is the ID of the record, which is declared as the
The
value of the record is declared as the The The expressions in
|
<request name="Delete" service="Database" fields="DELETE id"> <prop name="expr.src" content-type="text/x-erlang"><![CDATA[ Id = get("id"), NewTable = maps:remove(Id, Table), "Ok". ]]></prop> <reply name="Ok" fields="OK"/> </request> |
The Delete operation updates the Table
variable, and thus creates a new map.The new map contains all previous records, except the one deleted. The input field of the operation, The
expressions in
In this case, the |