# Inter-Service Referencing

Inter-service referencing enables resources in one service commissioning file to depend on resources defined in other service commissioning files. This allows you to build modular, reusable services that can be composed together to create complex architectures.

By default, resources within a service commissioning file can only reference other resources in the same file. Inter-service referencing breaks this limitation, allowing you to:

* Create reusable connection definitions that multiple services can share.
* Build modular architectures where services have clear separation of concerns.
* Manage complex deployments by breaking them into smaller, focused components.

## Referencing Resources Across Services

To reference a resource in another service:

{% code lineNumbers="true" %}

```yaml
!ref '${otherServiceName}::resourceId'
```

{% endcode %}

Where:

* `otherServiceName` is the service that contains the target Service ID.
* `resourceId` is the ID of the resource in the target service.

To reference a resource from another service:

* **Do not hardcode the Service ID** directly.
* Instead, use a parameter that dynamically provides the correct Service ID at runtime.

parameterName is a parameter that contains the target Service ID resourceId is the ID of the resource in the target service

For example, if you define a parameter named `otherServiceName`, you can reference a resource in that service as:

{% code lineNumbers="true" %}

```yaml
!ref '${otherServiceName}::resourceId'
```

{% endcode %}

For further details, see [Service ID](https://docs.cybus.io/2-0-6/documentation/services/serviceid) and [Resource ID](https://docs.cybus.io/2-0-6/documentation/service-commissioning-files/resources#resource-id).

## Service Dependency Behavior

Connectware enables advanced relationships between services. Understanding how these interdependencies behave at runtime is crucial for correct deployment and maintenance.

* **Child services**: Services that reference other services.
* **Parent services**: Services that are referenced by others.

### Installation Order

* Install parent services first (recommended):
  * Service relations are created automatically during installation.
  * Both parent and child services can be installed with `targetState=enabled`.
  * This is the most reliable approach and avoids issues during activation.
* Install child services first (alternative):
  * Service relations are only established once the parent service becomes available and the child is enabled.
  * The dependent (child) service can only be installed with `targetState=disabled`.
  * Attempting to install and enable a child without its parent will fail until the parent is added. Logs in Service Manager will indicate the unresolvable reference.

For more details, see [targetState](https://docs.cybus.io/2-0-6/documentation/service-commissioning-files/resources/cybus-endpoint#targetstate).

### Expected Behaviors

Following are four scenarios and how the services behave in each case:

1. All services are installed and then enabled in parents/child order.
   1. This behaves as any other set of services.
   2. Disabling a `Parent Service` will disable all its `Child Services`.
2. All services are installed and then enabled in random order.
   * `Child Services` will not wait on the `Enabling` state and the request will fail.
3. `Child Services` are installed first without `Parent Service` present.
   1. These services must be installed with targetState=disabled.
   2. Trying to enable them before the parent exists will fail, with Service Manager logs indicating the missing reference.
   3. Once the parent service is added, enabling the child succeeds and the relation is established.
4. Parents services are installed first without child presents.
   * No special behavior. When child services are later added, this behaves as cases 1 or 2.

### Example

The following service commissioning files demonstrate the behaviors described above:

1. A Cybus::Container running a database
   * Service ID will be `mssqldatabase`
2. A Cybus::Connection connecting to the database
   * Service ID will be `serviceaconnection`
3. A Cybus::Endpoint using referencing to use that Connection
   * Service ID will be `servicebendpoint`

By deploying these, you can reproduce all the installation and dependency behaviors.

#### SQL Database

{% code lineNumbers="true" %}

```yaml
description: MSSQL Database
metadata:
  name: MSSQL Database

definitions:
  password: password1234!

resources:
  mssqlDatabase:
    type: Cybus::Container
    properties:
      image: mcr.microsoft.com/mssql/server
      ports:
        - '1433:1433'
      environment:
        ACCEPT_EULA: 'Y'
        SA_PASSWORD: !ref password
```

{% endcode %}

#### SQL Connection

{% code lineNumbers="true" %}

```yaml
description: MSSQL Connection
metadata:
  name: Service A Connection

parameters:
  ip_host:
    type: string
    title: IP address or hostname where Connectware is installed

definitions:
  port: 1433
  database: master
  username: sa
  password: password1234!

resources:
  mssqlConnection:
    type: Cybus::Connection
    properties:
      protocol: Mssql
      connection:
        host: !ref ip_host
        port: !ref port
        username: !ref username
        password: !ref password
        database: !ref database
        useEncryption: false
```

{% endcode %}

#### SQL Endpoint

{% code lineNumbers="true" %}

```yaml
description: Service B
metadata:
  name: Service B Endpoint

parameters:
  mssqlConnectionServiceId:
    type: string
    title: Service ID of the MSSQL Connection

resources:
  mssqlVersionB:
    type: Cybus::Endpoint
    properties:
      protocol: Mssql
      connection: !ref '${mssqlConnectionServiceId}::mssqlConnection'
      subscribe:
        query: 'SELECT @@version'
        interval: 1000
```

{% endcode %}
