Location Service

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

This DSL provides following APIs:

register

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

Registration can be one of:

  1. AkkaRegistration
  2. HttpRegistration
  3. TcpRegistration
Kotlin
// 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 provided Connection from Location Service

Connection can be one of:

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

unregister(HttpConnection(componentId))

findLocation

This DSL look up for provided Connection in Location Service and returns corresponding Location or null if not found.

Kotlin
val 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 keeps looking for provided Connection in Location Service for the provided/default duration and returns corresponding Location or null if not found after duration exhausts.

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

val location: AkkaLocation? = resolveLocation(assemblyConnection)

// 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
val allLocations: List<Location> = listLocations()

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

listLocationsBy

Following various APIs are provided for listing locations with filtering criteria:

ComponentType

Filters locations based on provided ComponentType, for example, HCD, Assembly, Sequencer etc.

Following example demonstrate a use case where script sends Offline command to all the Assemblies.

Kotlin
onSetup("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, 10.minutes) }
    assemblies.forEach { it.goOffline() }
}

ConnectionType

Filters locations based on provided ConnectionType, for example, AkkaType, HttpType, TcpType etc.

Following example demonstrate a use case where script locks all the components i.e. Assemblies and HCD’s.

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

    // 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")
        }
    }
}
Note

Following import is required for creating ConnectionType and ComponentType

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

Hostname

Filters locations based on provided hostname.

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

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

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

Prefix

Filters locations based on provided Prefix.

In the following example, we are listing all the componenst registered using Prefix: IRIS.filter.wheel where IRIS is a Subsystem and filter.wheel is a component name

Kotlin
val irisPrefix = Prefix("IRIS.filter.wheel")
val irisComponents: List<Location> = listLocationsBy(irisPrefix)

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

        HCD -> info("$irisPrefix is registered as HCD with location: $it")

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

onLocationTrackingEvent

This DSL allows you to add a callback on every location changed event which is represented by TrackingEvent.

TrackingEvent has following two subclasses

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

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

Kotlin
onObserve("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 purpose and is not part of DSL. sendUIEvent publish SystemEvent with provided message.

Source code for examples