Controlling service instances

By default, a service instantiates on any node that happens to be running. You can change the default behaviour - for example to select on which node the instance is run, or to decide when or why the service instance comes down.

About this task

You can use the instance.spec property to change the default behaviour of service instantiation. The property specifies:

  • Which service instance to use if any instance matches the instance specification
  • Where to create a new instance if no existing instance matches the specification

Procedure

  1. Open the Editor.
  2. Add or select a service you want to modify.
  3. Add the service the instance.spec property.
  4. Define the instance specification by adding instance.spec an expressions list content, attributes or both.
    Expressions/Attributes Description
    Expressions list Content of instance.spec is an expressions list in the form of an Erlang map, with the following keys, all of which are optional:
    • action
    • node
    • domains
    • ttl
    • key

    See instance.spec expressions.

    Attributes instance.spec with the following attributes, all of which are optional:
    • node
    • domains
    • ttl

    See instance.spec attributes.

    A combination of both You can use both attributes and expressions.

    If a specification is added both as an attribute and as an Erlang record, the latter overrides the former.

    For example, if a node is specified both in the attribute and the Erlang map, the node specified in the Erlang map takes precedence.

  5. Optional: If you use expressions, you can define variables for the values and bind them to fields of operations on the service. To do so:
    1. Define a variable as an attribute of the instance.spec property and give it an initial value
    2. In the Erlang map, define this variable as a value that corresponds to a key
    3. Add the instance.bind property to an operation implemented by the service
    4. Bind the input or output field of the operation to the same variable defined in the Erlang map
      <!-- The value of the domain field - a string -
           is used to select the node where the
           Sequencer service is instantiated  -->
      
      <service name="Sequencer" 
        provision="sequencer">
        <prop name="instance.spec" 
          content-type="text/x-erlang" 
          Domains="foo"><![CDATA[
      #{
       domains => Domains
       }.
        ]]></prop>
      </service>
      <notify name="myNotify" 
        service="Sequencer" 
        fields="domain">
        <prop name="instance.bind" 
          Domains="domain"/>
      </notify>

Results

Depending on your specifications, the service can only instantiate on certain nodes, or an instance goes down after a period of inactivity, and so on.

instance.spec expressions

<service name="Service" 
  provision="expr">
  <prop name="instance.spec" 
    content-type="text/x-erlang"><![CDATA[
#{
  action => up,               % up|down
  ttl => 1000,                % Time in milliseconds 
  key => Meta(user),          % Any Erlang term
  node => node(),             % node() is current node
  domains => "domain.local"   % String
}.
  ]]></prop>
</service>
Important: The expressions list must end with a full stop.
Table 1. instance.spec Erlang keys
Key Default value Description
action up Possible values:
  • up - The instance does not come down unless a down action or a manual user action brings it down
  • down - The instance comes down or does not come up until an up action brings it up
ttl n/a It stands for Time To Live. A period of inactivity in milliseconds, or other specified time unit, after which the service instance comes down.
Note: If combined with an up action, the instance is automatically brought down after the specified period of inactivity.
key undefined An Erlang term that can be any user specified key. For example, a metadata - like the name of a user, or a session ID.
domains undefined A space separated list of domains in which the service is to be instantiated. The list has a hierarchy where the node that has the first of the listed domains is selected; or if no node has it, the node that has the second of the listed domains is selected, and so on.
Note: The domains of a node are specified in the sys.config of the node.

By default, all nodes have the following domains:

  • domain.local
  • {{Name}} - The name of the node. For example, sse1.
  • {{Host}} - Either the hostname or the IP address of the node. For example, 127.0.0.1 or somedomain.com.
Tip: Make sure to define multiple domains to provide fallbacks. At execution time, always the first available domain is selected.
node undefined It specifies the node on which the service is to be instantiated.

If node is specified, it overrides domains.

node() means the current node.

Note: Specifying both node and domains is redundant. Since multiple nodes can share the same domains, using domains provides more flexibility.

instance.spec attributes

<service name="MyService" 
  provision="expr">
  <prop name="instance.spec" 
    domains="foo.local fallback" 
    ttl="5s"/>
</service>
Table 2. instance.spec attributes
Attribute Description
domains A space separated list of domains in which the service is to be instantiated. The list has a hierarchy where the node that has the first of the listed domains is selected; or if no node has it, the node that has the second of the listed domains is selected, and so on.
Note: The domains of a node are specified in the sys.config of the node.

By default, all nodes have the following domains:

  • domain.local
  • {{Name}} - The name of the node. For example, sse1.
  • {{Host}} - Either the hostname or the IP address of the node. For example, 127.0.0.1 or somedomain.com.
Tip: Make sure to define multiple domains to provide fallbacks. At execution time, always the first available domain is selected.
node It specifies the node on which the service is to be instantiated.

If node is specified, it overrides domains.

Note: Specifying both node and domains is redundant. Since multiple nodes can share the same domains, using domains provides more flexibility.
ttl It stands for Time To Live. A period of inactivity in milliseconds, or other specified time unit, after which the service instance comes down.
[Var] A variable defined as an attribute of instance.spec. This variable can be referenced in the expressions list content of the property.

Operations on the service can update this variable using the instance.bind property.