Location Service

The Location Service DSL is a wrapper over the Location Service module provided by CSW. You can refer the detailed documentation of the Location Service provided by CSW here.

This DSL provides the following APIs:

register

This DSL registers a provided Registration with the Location Service and returns a RegistrationResult, which contains the Location with which a component is registered and a handle for un-registration.

Registration can be one of:

  1. AkkaRegistration
  2. HttpRegistration
  3. TcpRegistration
Kotlin
source// register HTTP service running at port 8080 and routes are served from /routes endpoint
val registrationResult: RegistrationResult =
        register(HttpRegistration(httpConnection, port, "/routes"))

// location which is registered with Location Service
val location: Location = registrationResult.location

// unregisters location from Location Service which triggers LocationRemoved event
registrationResult.unregister()

unregister

This DSL un-registers the provided Connection from Location Service

Connection can be one of:

  1. AkkaConnection
  2. HttpConnection
  3. TcpConnection
Kotlin
sourceval sourcePrefix: Prefix = cmd.source()
val componentId = ComponentId(sourcePrefix, Service)

unregister(HttpConnection(componentId))

findLocation

This DSL looks up the provided Connection in the Location Service and returns the corresponding Location, or null, if not found.

Kotlin
sourceval prefix: Prefix = cmd.source()
val assemblyConnection = AkkaConnection(ComponentId(prefix, Assembly))

val location: AkkaLocation? = findLocation(assemblyConnection)

// send a successful event to UI if assembly location is found
location?.let { sendUIEvent("Resolved assembly location: $it") }

resolveLocation

This DSL looks for the specified Connection in the Location Service for the optionally specified duration (default is 5 seconds) and returns the corresponding Location. If the location is not resolved within the time limit, null is returned.

Kotlin
sourceval prefix: Prefix = cmd.source()
val assemblyConnection = AkkaConnection(ComponentId(prefix, Assembly))

val location: AkkaLocation? = resolveLocation(assemblyConnection, Duration.seconds(10))

// send a successful event to UI if assembly location is found
location?.let { sendUIEvent("Resolved assembly location: $it") }

listLocations

Lists all the locations currently registered with the Location Service.

Kotlin
sourceval allLocations: List<Location> = listLocations()

// publish all locations to UI in the format of [location1, location2, ...]
sendUIEvent(allLocations.joinToString(prefix = "[", postfix = "]"))

listLocationsBy

The following various APIs are provided for listing locations with filtering criteria:

ComponentType

Filters locations based on provided ComponentType. A DSL is provided to specify the type, which can be one of: HCD, Assembly, Sequencer, SequenceComponent, Container, Service

The following example demonstrates a use case where the script sends an Offline command to all of the Assemblies currently registered.

Kotlin
sourceonSetup("offline-assemblies") {
    // list all Assembly components
    val assemblyLocations: List<Location> = listLocationsBy(Assembly)

    // create Assemblies from locations and send offline command to each one of them
    val assemblies = assemblyLocations.map { Assembly(it.prefix, Duration.minutes(10)) }
    assemblies.forEach { it.goOffline() }
}

ConnectionType

Filters locations based on provided ConnectionType. A DSL is provided to specify the type, which can be one of: AkkaType, HttpType, TcpType.

The following example demonstrates a use case where the script locks all the Akka Type components i.e. Assemblies and HCD’s.

Kotlin
sourceonSetup("lock-all-components") {
    val timeout = Duration.minutes(10)
    val leaseDuration = Duration.minutes(20)

    // list all akka components
    val akkaLocations: List<Location> = listLocationsBy(AkkaType)

    // filter HCD's and Assemblies and send Lock command
    akkaLocations.forEach { location ->
        val compId: ComponentId = location.connection.componentId
        val compType: ComponentType = compId.componentType
        val prefix = location.prefix

        // create Assembly or Hcd instance based on component type and send Lock command
        when (compType) {
            Assembly -> Assembly(prefix, timeout).lock(leaseDuration)

            HCD -> Hcd(prefix, timeout).lock(leaseDuration)

            else -> warn("Unable to lock component $compId, Invalid component type $compType")
        }
    }
}
Required import for Location Service APIs

The following import is required for using ConnectionType and ComponentType:

import esw.ocs.dsl.highlevel.models.*

Hostname

Filters locations based on the provided hostname (or IP address).

In the following example, all the components running on IRIS (hostname: 10.1.1.1) machine are listed.

Kotlin
source// list all the components running on IRIS machine
val irisMachineHostname = "10.1.1.1"
val irisMachineLocations: List<Location> = listLocationsByHostname(irisMachineHostname)

sendUIEvent("IRIS machine running components: [$irisMachineLocations]")

Prefix

Filters locations based on the provided prefix string. As with the CSW Location Service, the method filters for all locations with prefixes that start with the provided string.

In the following example, it receives a list of all the components registered with prefixes that start with: IRIS.filter.

Kotlin
sourceval irisPrefixString ="IRIS.filter."
val irisComponents: List<Location> = listLocationsBy(irisPrefixString)

// log Assembly and HCD location
irisComponents.forEach {
    when (it.connection.componentId.componentType) {
        Assembly -> info("Assembly starting with $irisPrefixString is registered with location: $it")

        HCD -> info("HCD starting with $irisPrefixString is registered with location: $it")

        else -> error("Invalid location: $it found for $irisPrefixString")
    }
}

onLocationTrackingEvent

This DSL allows you to add a callback that is called when the location of the specified connection changes, which is represented by a TrackingEvent.

TrackingEvent has following two subclasses

  1. LocationUpdated: Published when the location is registered with the Location Service

  2. LocationRemoved: Published when the location is removed from the Location Service

Kotlin
sourceonObserve("monitor-iris-sequencer") {
    val irisPrefix = Prefix("IRIS.darknight")
    val irisComponent = ComponentId(irisPrefix, Sequencer)
    val irisSequencerConnection = AkkaConnection(irisComponent)

    // send UI events on iris sequencers location change
    onLocationTrackingEvent(irisSequencerConnection) {
        when (it) {
            is LocationUpdated ->
                sendUIEvent("[INFO] Location updated ${it.location()}")

            is LocationRemoved ->
                sendUIEvent("[ERROR] Location removed for connection: ${it.connection()}")
        }
    }
}
Note

sendUIEvent used in above examples is just for demonstration purposes and is not part of DSL. The sendUIEvent method, defined elsewhere in the script, publishes a SystemEvent with the provided message.

Source code for examples