Waiting for engine...
Skip to main content

Implementing Singleton Listen operations

The Connector SDK includes a SingletonListenOperation interface (see the Javadocs) that you can use to extend the ListenOperation class, allowing Listen operations for SDK connectors to run in singleton mode in single-tenant and multi-tenant containers, and on an Execution worker. Running in singleton mode is useful when managing access to a shared resource and you must have only one instance of the same class.

How Singleton Listen operations work

Use the following information to understand how running listen operations in singleton mode works.

Containers

  • Only one instance of a singleton operation starts for each container. For multi-node containers, the operation starts on only one node.
  • Singleton operations do not cross containers. The listener runs on all Runtimes in the environment.

Listen Manager/Connector Servers

  • The Listen Manager does not currently run in singleton mode. The manager starts on every node, and the Listen operation only starts on one node.
  • If you deploy both singleton and non-singleton listen operations, the manager and non-singleton operations start on all nodes. Singleton operations, however, only start on one node.
  • Listen Managers are limited to the version of the deployed connection component; managers only manage listen operations using the same version of the connection. If you deploy multiple singleton listen operations with each having a different version of the connection, they operate in singleton mode. However, they do not share a Listen Manager and are not guaranteed to run on the same node.

Listener startup

  • All SDK listeners start using the "async" start up mode. In this mode, the Listen Manager/Connector Servers start in a background task with the timeout controlled by the Connector Server Startup Timeout container property (com.boomi.container.connectorServer.startupTimeout). The default timeout value is 15 minutes. Long running or indefinite Listener startup should be canceled after the Connector Server Startup Timeout container property expires, and should not impact other Atom operations.

    note

    Several container properties are available, determining how singleton listen operations work and which implementation mode to use. For more information, see the section Singleton container properties in this topic.

  • When starting the Listen operation on the node, the Listen Manager determines (based on which implementation you enable in the container properties) the active node by either obtaining a file lock, or recording the name of the node to lock. The lock files appear in a dedicated bounds directory and the Listen Manager attempts to delete the lock file when released.

Listener shutdown

  • When a Runtime/Execution Worker tries to shut down a listener, it currently gives 10 seconds to that listener to shut down before forcefully shutting it down.

  • You can now set a custom shutdown timeout for the listener using a container property com.boomi.container.connectorServer.listenerShutdownTimeout. This can be set via the Custom tab of properties for a cloud or a local atom. The default timeout value is 10000 ms (10 seconds) with a maximum value of 600000 ms (10 minutes). The unit of time entered should be in milliseconds. Any value that is less than or equal to 0 will be auto reset to the default of 10 seconds and any value greater than 10 minutes will be auto set to the maximum allowed value of 10 minutes.

Distribution

  • Connector SDK listen operations can be configured to use the DistributionMode as a part of the SubmitOption. The DistributionMode accepts the following values to determine how submitted process executions are distributed and executed in a multi-node molecule: “LOCAL_ONLY” and “PREFER_REMOTE”. This configuration attempts to distribute process executions across the container when running in singleton mode. PREFER_REMOTE is only a preference and low latency processes do not honor the preference.

Code sample

Here is a simple implementation of a singleton listen operation with comments included for context:

note

You can find this code sample in the connector-sdk-samples-sources JAR file, available in the Connector SDK artifacts available from the public repository.

Code sample: Singleton listen operation

// Copyright (c) 2020 Boomi, Inc.
package com.boomi.connector.sample.listen.singleton;

import com.boomi.connector.api.OperationContext;
import com.boomi.connector.api.listen.ListenManager;
import com.boomi.connector.api.listen.Listener;
import com.boomi.connector.api.listen.SingletonListenOperation;
import com.boomi.connector.sample.listen.SampleConsumer;
import com.boomi.connector.sample.listen.SimpleMessageHandler;
import com.boomi.connector.sample.listen.SampleConsumer.SingleMessageHandler;
import com.boomi.connector.sample.listen.submit.ConfigurableSubmitListenOperation;
import com.boomi.connector.util.listen.UnmanagedListenOperation;

/**
* Simple {@link SingletonListenOperation} that demonstrates using an operation property to determine if the listener
* should operate in "singleton mode". For simplicity, this is an {@link UnmanagedListenOperation}.
*/
public class SimpleSingletonOperation extends UnmanagedListenOperation
implements SingletonListenOperation<ListenManager> {

/**
* The consumer here is just created when the operation is instantiated. You could also defer the creation until the
* operation is started (i.e., create the consumer in {@link #start(Listener)}.
*/
private final SampleConsumer _consumer = new SampleConsumer();

/**
* Creates a new instance using the provided context
*/
protected SimpleSingletonOperation(OperationContext context) {
super(context);
}

/**
* Starts the listen operation by opening a {@link SampleConsumer} connection and then registering a
* {@link SingleMessageHandler} backed by the provided {@link Listener}.
*/
@Override
protected void start(Listener listener) {
_consumer.connect();
_consumer.register(new SimpleMessageHandler(listener));
}

/**
* Stops the listen operation by closing the {@link SampleConsumer} connection. This assumes that the message
* handler is deregistered when the consumer is disconnected. If that's not the case, the handler can be
* deregistered here before disconnecting the client which is demonstrated in
* {@link ConfigurableSubmitListenOperation}
*/
@Override
public void stop() {
_consumer.disconnect();
}

/**
* Assumes a boolean operation property with id "isSingleton". When invoked by the container, this method will
* return true if the operation property is enabled, false otherwise.
*/
@Override
public boolean isSingleton() {
return getContext().getOperationProperties().getBooleanProperty("isSingleton", false);
}

}

Developing Connectors to Run in Singleton mode

  1. Singleton Listen operations are automatically enabled for all single-tenant containers (runtimes and runtime cloud clusters) and multi-tenant containers (Clouds).

  2. To run in singleton mode on an Execution Worker, you must also enable Secure Listen for a Runtime cloud. To learn more, see the topic Enabling Secure Listen for a Runtime cloud.

  3. Implement the SingletonListenOperation interface in your connector code.

  4. Implement an isSingleton method in your connector code to return true indicating that the operation should run in singleton mode.

Singleton container properties

The following container properties are available, determining how singleton listen operations work and which implementation mode to use:

  • com.boomi.container.bounds.renew.interval

    Use this property to schedule a renewal interval (any value, in milliseconds) that the bounded service manager uses to renew locks. Locks are renewed on a scheduled interval to ensure the node name exists and the lock is held.

    • If left blank, the default value (half the refresh interval) is used.
    • If you enter a value less than or equal to zero (0), the renewal interval is turned off.
    Attention

    Locks expire when a value two times the renewal interval is met, or never expire when the renewal interval is less than or equal to zero (0).

  • com.boomi.container.bounds.refresh.interval

    note

    The previous interval property com.boomi.container.bounded.listen.refresh.interval will continue to work for the near future, but this new non-listener-specific interval property will take precedence.

    Use this property to set a refresh interval (any value, in milliseconds) that the bounded service manager uses to refresh locks. The renew and refresh properties work in combination to ensure locks are held.

    • If left blank, the default value (1800000 milliseconds) is used.

Singleton file locking and logging

When the bounded service manager starts for a Singleton Listen operation, it creates a bounds directory and locks a file. To help you determine where the lock is acquired, the ID of the lock and instance are logged. The file name and file path are also logged.

Before attempting to acquire a lock, the full path to the lock file is logged. The log entry will be similar to the following example:

[com.boomi.container.bounds.FileLockFactory getLockFile] attempting to acquire /mnt/shared/Molecule_ConnectivityMolecule/bounds/b1d6507d-64f3-4391-bc7e-1855491c4b88.1.lck]

After attempting to acquire a lock, the lock ID and lock is logged. If the lock is successfully acquired, the log entry will be similar to the following example:

[com.boomi.container.bounds.FileLockFactory$BoundedFileLock acquire] b1d6507d-64f3-4391-bc7e-1855491c4b88.1 sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]

If the lock is not acquired, the log entry will be similar to the following example:

[com.boomi.container.bounds.FileLockFactory$BoundedFileLock acquire] b1d6507d-64f3-4391-bc7e-1855491c4b88.1 (no lock)]

Before releasing a lock, the lock ID and lock are logged. The log entry will be similar to the following example:

[2022_04_21.container.atom02.log:Apr 21, 2022 3:42:42 PM UTC FINE [com.boomi.container.bounds.FileLockFactory getLockFile] /mnt/shared/Molecule_ConnectivityMolecule/bounds/b1d6507d-64f3-4391-bc7e-1855491c4b88.1.lck]
Attention

If a node fails to release a lock, a WARNING is logged in the container logs.

On this Page