package io.cattle.platform.servicediscovery.process;
import static io.cattle.platform.core.model.tables.AccountLinkTable.*;
import static io.cattle.platform.core.model.tables.ServiceConsumeMapTable.*;
import static io.cattle.platform.core.model.tables.ServiceTable.*;
import io.cattle.platform.core.constants.AccountConstants;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.model.Account;
import io.cattle.platform.core.model.AccountLink;
import io.cattle.platform.core.model.Service;
import io.cattle.platform.core.model.ServiceConsumeMap;
import io.cattle.platform.engine.handler.HandlerResult;
import io.cattle.platform.engine.handler.ProcessPostListener;
import io.cattle.platform.engine.process.ProcessInstance;
import io.cattle.platform.engine.process.ProcessState;
import io.cattle.platform.eventing.EventService;
import io.cattle.platform.lock.LockCallbackNoReturn;
import io.cattle.platform.lock.LockManager;
import io.cattle.platform.object.process.StandardProcess;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.object.util.ObjectUtils;
import io.cattle.platform.process.common.handler.AbstractObjectProcessLogic;
import io.cattle.platform.process.common.lock.AccountLinksUpdateLock;
import io.cattle.platform.servicediscovery.service.ServiceDiscoveryService;
import io.github.ibuildthecloud.gdapi.condition.Condition;
import io.github.ibuildthecloud.gdapi.condition.ConditionType;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.TransformerUtils;
@Named
public class AccountLinkRemove extends AbstractObjectProcessLogic implements ProcessPostListener {
@Inject
ServiceDiscoveryService sdSvc;
@Inject
LockManager lockManager;
@Inject
EventService eventService;
@Override
public HandlerResult handle(ProcessState state, ProcessInstance process) {
AccountLink accountLink = (AccountLink) state.getResource();
updateServices(accountLink);
Account account = objectManager.loadResource(Account.class, accountLink.getAccountId());
if (account == null) {
return null;
}
regenerateAccountLinks(account);
return null;
}
@SuppressWarnings("unchecked")
private void updateServices(AccountLink accountLink) {
List<? extends ServiceConsumeMap> consumeMaps = objectManager.find(ServiceConsumeMap.class,
SERVICE_CONSUME_MAP.ACCOUNT_ID,
accountLink.getAccountId(), SERVICE_CONSUME_MAP.REMOVED, null);
List<? extends Service> services = objectManager.find(Service.class, SERVICE.ACCOUNT_ID,
accountLink.getLinkedAccountId(), SERVICE.REMOVED, null);
List<Long> serviceIds = (List<Long>) CollectionUtils.collect(services,
TransformerUtils.invokerTransformer("getId"));
for (ServiceConsumeMap consumeMap : consumeMaps) {
if (serviceIds.contains(consumeMap.getConsumedServiceId())) {
objectProcessManager.scheduleStandardProcessAsync(StandardProcess.REMOVE, consumeMap, null);
}
}
}
protected void regenerateAccountLinks(final Account account) {
lockManager.lock(new AccountLinksUpdateLock(account.getId()),
new LockCallbackNoReturn() {
@Override
public void doWithLockNoResult() {
List<? extends AccountLink> allLinks = objectManager.find(AccountLink.class,
ACCOUNT_LINK.ACCOUNT_ID, account.getId(),
ACCOUNT_LINK.REMOVED, null, ACCOUNT_LINK.STATE, new Condition(ConditionType.NE,
CommonStatesConstants.REMOVING));
List<Long> newLinks = new ArrayList<>();
for (AccountLink aLink : allLinks) {
newLinks.add(aLink.getLinkedAccountId());
}
List<Long> existingLinks = DataAccessor.fieldLongList(account,
AccountConstants.FIELD_ACCOUNT_LINKS);
if (existingLinks.containsAll(newLinks) && newLinks.containsAll(existingLinks)) {
return;
}
objectManager.setFields(account, AccountConstants.FIELD_ACCOUNT_LINKS, newLinks);
ObjectUtils.publishChanged(eventService, objectManager, account);
}
});
}
@Override
public String[] getProcessNames() {
return new String[] { "accountlink.remove" };
}
}