All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.services.mt.impl.AsyncSidecarUpgradeHelper Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.services.mt.impl;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sap.cloud.mt.subscription.Subscriber;
import com.sap.cloud.mt.subscription.exceptions.AuthorityError;
import com.sap.cloud.mt.subscription.exceptions.InternalError;
import com.sap.cloud.mt.subscription.exceptions.NotFound;
import com.sap.cloud.mt.subscription.exceptions.NotSupported;
import com.sap.cloud.mt.subscription.exceptions.ParameterError;

// TODO this code should be moved to the MT Lib
public class AsyncSidecarUpgradeHelper {

	private static final Logger logger = LoggerFactory.getLogger(AsyncSidecarUpgradeHelper.class);
	private static final ObjectMapper mapper = new ObjectMapper()
			.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
	private static final String SIDECAR_STATUS_RUNNING = "RUNNING";
	private static final String SIDECAR_STATUS_FAILED = "FAILED";
	private static final Set SIDECAR_SUCCESS_STATUSES = new HashSet<>(Arrays.asList("SUCCESS", "NON-EXISTENT"));

	private final Subscriber subscriber;

	public AsyncSidecarUpgradeHelper(Subscriber subscriber) {
		this.subscriber = subscriber;
	}

	public void deploy(List tenants) throws AuthorityError, ParameterError, InternalError, NotSupported, NotFound {
		try {
			String jobIdJson = subscriber.setupDbTablesAsync(tenants);
			String jobId = mapper.readValue(jobIdJson, JobIdResult.class).jobID;

			String statusJson;
			SidecarResult sidecarResult;
			do {
				Thread.sleep(2000);
				statusJson = subscriber.updateStatus(jobId);
				sidecarResult = mapper.readValue(statusJson, SidecarResult.class);
			} while (SIDECAR_STATUS_RUNNING.equals(upper(sidecarResult.status)));

			boolean failed = SIDECAR_STATUS_FAILED.equals(upper(sidecarResult.status)) || // both
					sidecarResult.error != null; // classic MTX
			if (!failed && sidecarResult.result != null && sidecarResult.result.tenants != null) { // classic MTX
				failed = sidecarResult.result.tenants.values().stream().anyMatch(tenant -> !SIDECAR_SUCCESS_STATUSES.contains(upper(tenant.status)));
			}
			if (!failed && sidecarResult.tenants != null) { // streamlined MTX
				failed = sidecarResult.tenants.values().stream().anyMatch(tenant -> SIDECAR_STATUS_FAILED.equals(upper(tenant.status)));
			}

			if (failed) {
				throw new InternalError("Updating failed with response '" + statusJson + "'");
			}
			logger.debug("Updating succeeded with response '{}'", statusJson);
		} catch (JsonProcessingException e) {
			throw new InternalError("Failed to parse sidecar response", e);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}

	}

	private static final class SidecarResult {
		public String status; // both
		public String error; // classic MTX
		public DeployResult result; // classic MTX
		public Map tenants; // streamlined MTX

		private static final class DeployResult {
			public Map tenants;

			private static final class TenantResult {
				public String status;
			}
		}
	}

	private static final class JobIdResult {
		public String jobID;
	}

	private String upper(String s) {
		return s == null ? s : s.toUpperCase(Locale.ENGLISH);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy