tryDeployment method

Future<void> tryDeployment(
  1. Study<PrimaryDeviceDeployment> study,
  2. DeviceRegistration registration
)

Tries to deploy the study if it's ready to be deployed by registering the client device using registration and verifying the study is ready for deployment on this device. In case already deployed, nothing happens.

Throws IllegalArgumentException if:

  • a deployment with study deployment ID matching this study does not exist
  • device role name of study is not present in the deployment or is already registered and a different registration is specified
  • registration of this client is invalid for the expected device role name or has a device ID which is already in use by the registration of a different device.

Implementation

Future<void> tryDeployment(
  Study study,
  DeviceRegistration registration,
) async {
  final studyDeploymentId = study.studyDeploymentId;
  final deviceRoleName = study.deviceRoleName;
  StudyDeploymentStatus? deploymentStatus;

  // Register the client device in the study deployment.
  try {
    deploymentStatus = await deploymentService.registerDevice(
      studyDeploymentId,
      deviceRoleName,
      registration,
    );
  } catch (error) {
    // Note that this device may already be registered which will throw an
    // exception from the deployment service. But, this should not prevent
    // getting the deployment.
    study.deploymentError(
      "$runtimeType - Error registering '${study.deviceRoleName}' as primary device.\n$error",
    );
    deploymentStatus = null;
  }

  // If we didn't get a deployment status from registration, try to get it directly.
  deploymentStatus ??= await getStudyDeploymentStatus(study);

  // If we still don't have a deployment status, mark this as an error and exit.
  if (deploymentStatus == null) {
    study.deploymentError(
      "No study deployment with ID '$studyDeploymentId' found when trying to register device "
      "with role name '$deviceRoleName'.",
    );
    return;
  }

  // Update study with new deployment status.
  study.deploymentStatusReceived(deploymentStatus);
  final studyStatus = deploymentStatus;
  final deviceStatus = studyStatus.getDeviceStatusByRoleName(deviceRoleName);

  // The following statement is from CARP Core Kotlin.
  // However, this has been removed here in order to allow for re-deployment,
  // i.e., cases where we want to refresh the deployment information from the
  // deployment service.
  // // Early out in case state indicates the device is already deployed.
  // if (deviceStatus.status == DeviceDeploymentStatusTypes.Deployed) return;

  // Early out in case state indicates that deployment cannot yet be obtained.
  if (!deviceStatus.canObtainDeviceDeployment) return;

  // Get deployment information.
  final device = deviceStatus.device;
  PrimaryDeviceDeployment? deployment;
  try {
    deployment = await deploymentService.getDeviceDeploymentFor(
      studyDeploymentId,
      deviceRoleName,
    );
  } catch (error) {
    study.deploymentError(
      "$runtimeType - Error getting deployment information.\n$error",
    );
    deploymentStatus = null;
  }

  if (deployment == null) {
    study.deploymentError(
      "$runtimeType - Deployment for device role name '$deviceRoleName' "
      "in study deployment '$studyDeploymentId' is not available.",
    );
    return;
  }

  if (deployment.deviceConfiguration.roleName != deviceRoleName) {
    study.deploymentError(
      "The device role name of the deployment is '${deployment.deviceConfiguration.roleName}', "
      "which does not match the requested device role name '$deviceRoleName'.",
    );
    return;
  }

  // notify the study that the deployment has been received
  study.deviceDeploymentReceived(deployment);

  final remainingDevicesToRegister = studyStatus.deviceStatusList
      .map((status) => status.device)
      .where(
        (it) =>
            (deviceStatus.remainingDevicesToRegisterBeforeDeployment ?? [])
                .contains(it.roleName),
      )
      .toSet();

  // Stop here in case devices need to be registered before being able to complete deployment.
  if (remainingDevicesToRegister.isNotEmpty) return;

  // Notify deployment service of successful deployment.
  try {
    final deployedStatus = await deploymentService.deviceDeployed(
      studyDeploymentId,
      device.roleName,
      deployment.lastUpdatedOn,
    );
    if (deployedStatus != null) {
      study.deploymentStatusReceived(deployedStatus);
    }
  } catch (error) {
    // we only print a warning
    // see issue #50 - there is a bug in CAWS
    print(
      "$runtimeType - Error marking deployment '$studyDeploymentId' as deployed.\n$error",
    );
  }
}