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

com.sap.cds.feature.messaging.em.mt.service.EnterpriseMessagingMtHandler Maven / Gradle / Ivy

/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.feature.messaging.em.mt.service;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

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

import com.sap.cds.feature.messaging.em.mt.SubdomainUtils;
import com.sap.cds.feature.messaging.em.service.EnterpriseMessagingServiceConfiguration;
import com.sap.cds.services.environment.CdsProperties.Messaging.MessagingServiceConfig;
import com.sap.cds.services.handler.annotations.After;
import com.sap.cds.services.handler.annotations.On;
import com.sap.cds.services.handler.annotations.ServiceName;
import com.sap.cds.services.messaging.MessagingService;
import com.sap.cds.services.mt.DependenciesEventContext;
import com.sap.cds.services.mt.DeploymentService;
import com.sap.cds.services.mt.SubscribeEventContext;
import com.sap.cds.services.mt.TenantInfo;
import com.sap.cds.services.mt.TenantProviderService;
import com.sap.cds.services.mt.UpgradeEventContext;
import com.sap.cds.services.outbox.OutboxService;
import com.sap.cds.services.utils.CdsErrorStatuses;
import com.sap.cds.services.utils.ErrorStatusException;
import com.sap.cds.services.utils.environment.ServiceBindingUtils;

/**
 * Enterprise messaging related implementation of the multi tenancy subscription handler which is
 * responsible for providing the dependencies to the bound EM service instances and also tenant
 * messaging schema update on tenant subscription.
 */
@ServiceName(DeploymentService.DEFAULT_NAME)
public class EnterpriseMessagingMtHandler {

	private static final Logger logger = LoggerFactory.getLogger(EnterpriseMessagingMtHandler.class);

	@After
	public void addEnterpriseMessagingDependencies(DependenciesEventContext context) {

		final List> dependencies = context.getResult();

		// get all EM MT -> XSAPPNAME bindings
		Map bindings = new HashMap<>();
		context.getCdsRuntime().getEnvironment().getServiceBindings()
		.filter(b -> ServiceBindingUtils.matches(b, EnterpriseMessagingServiceConfiguration.BINDING_EM_LABEL) &&
				Objects.equals(EnterpriseMessagingServiceConfiguration.MT_INSTANCE_TYPE_VALUE, b.getCredentials().get(EnterpriseMessagingServiceConfiguration.INSTANCE_TYPE)))
		.forEach(b -> {
			bindings.put(b.getName().get(), b.getCredentials().get("xsappname").toString());
		});

		Set disabledServices = new HashSet<>();
		Map configs = context.getCdsRuntime().getEnvironment().getCdsProperties().getMessaging().getServices();

		// find first all disabled services
		configs.values().stream().filter(c -> !c.isEnabled()).forEach(service -> {
			if (bindings.containsKey(service.getName())) {
				disabledServices.add(bindings.get(service.getName()));
			} else if (bindings.containsKey(service.getBinding())) {
				disabledServices.add(bindings.get(service.getBinding()));
			} else if (bindings.size() == 1 && EnterpriseMessagingServiceConfiguration.BINDING_EM_LABEL.equals(service.getKind())) {
				disabledServices.add(bindings.values().stream().findFirst().get());
			}
		});

		// now check if at least any configured messaging services enables them again
		configs.values().stream().filter(c -> c.isEnabled()).forEach(service -> {
			if (bindings.containsKey(service.getName())) {
				disabledServices.remove(bindings.get(service.getName()));
			} else if (bindings.containsKey(service.getBinding())) {
				disabledServices.remove(bindings.get(service.getBinding()));
			} else if (bindings.size() == 1 && EnterpriseMessagingServiceConfiguration.BINDING_EM_LABEL.equals(service.getKind())) {
				disabledServices.remove(bindings.values().stream().findFirst().get());
			}
		});

		// check all non configured service/bindings
		bindings.values().stream().filter(xsappname -> !disabledServices.contains(xsappname)).forEach(xsappname -> {
			// append dependency if available
			logger.debug("Providing the enterprise-messaging service instance dependency '{}'", xsappname);
			dependencies.add(Collections.singletonMap("xsappname", xsappname));
		});
	}

	@On
	public void initializeServices(SubscribeEventContext context) {
		String tenantId = context.getTenant();
		String subdomain = (String) context.getOptions().get("subscribedSubdomain");

		// create the queue/topic subscriptions
		logger.info("Starting the enterprise-messaging tenant onboarding for tenant '{}' and subdomain '{}'", tenantId, subdomain);
		new SubdomainUtils(context.getCdsRuntime()).requestContextWithSubdomain(tenantId, subdomain, (requestContext) -> {
			context.getServiceCatalog().getServices(MessagingService.class)
					.map(OutboxService::unboxed)
					.filter(EnterpriseMessagingMtService.class::isInstance)
					.map(EnterpriseMessagingMtService.class::cast)
					.forEach(service -> service.init(tenantId));
		});
	}


	@On
	private void upgradeServices(UpgradeEventContext context) {
		logger.info("Starting the enterprise-messaging tenant upgrade");
		TenantProviderService tenantService = context.getServiceCatalog().getService(TenantProviderService.class, TenantProviderService.DEFAULT_NAME);
		Map tenantToSubdomain = new HashMap<>();
		tenantService.readTenantsInfo(Set.of(TenantInfo.TENANT, TenantInfo.SUBDOMAIN))
				.forEach(info -> tenantToSubdomain.put(info.getTenant(), info.getSubdomain()));
		context.getTenants().forEach(tenant -> {
			if (tenantToSubdomain.containsKey(tenant)) {
				SubdomainUtils utils = new SubdomainUtils(context.getCdsRuntime());
				utils.requestContextWithSubdomain(tenant, tenantToSubdomain.get(tenant), (tenantReqContext) -> {
					context.getCdsRuntime().getServiceCatalog().getServices(MessagingService.class)
							.map(OutboxService::unboxed)
							.filter(EnterpriseMessagingMtService.class::isInstance)
							.map(EnterpriseMessagingMtService.class::cast)
							.forEach(s -> s.init(tenant));
				});
			} else {
				throw new ErrorStatusException(CdsErrorStatuses.UNKNOWN_TENANT, tenant);
			}
		});
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy