Skip to content

Commit

Permalink
Tentatively fix db lockup by big certifications
Browse files Browse the repository at this point in the history
We try to break large number of certification case
modifications into smaller chunks of at most 60 deltas.

TODO: do the same for case creation; and check other similar places.
  • Loading branch information
mederly committed May 15, 2018
1 parent 0b82ffc commit f5e894a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
Expand Up @@ -207,7 +207,12 @@ public void recordLastCampaignIdUsed(String definitionOid, int lastIdUsed, Task

//region ================================ Stage open ================================

public List<ItemDelta<?,?>> getDeltasForStageOpen(AccessCertificationCampaignType campaign, AccessCertificationStageType stage, CertificationHandler handler, final Task task, OperationResult result)
public static class StageOpenDeltas {
public final List<ItemDelta<?,?>> casesDeltas = new ArrayList<>();
public final List<ItemDelta<?,?>> campaignDeltas = new ArrayList<>();
}

public StageOpenDeltas getDeltasForStageOpen(AccessCertificationCampaignType campaign, AccessCertificationStageType stage, CertificationHandler handler, final Task task, OperationResult result)
throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException {
Validate.notNull(campaign, "certificationCampaign");
Validate.notNull(campaign.getOid(), "certificationCampaign.oid");
Expand All @@ -220,26 +225,28 @@ public List<ItemDelta<?,?>> getDeltasForStageOpen(AccessCertificationCampaignTyp
ObjectTypeUtil.toShortString(campaign), stageNumber);
}

List<ItemDelta<?,?>> rv = new ArrayList<>();
StageOpenDeltas rv = new StageOpenDeltas();
if (stageNumber == 0) {
rv.addAll(caseHelper.getDeltasToCreateCases(campaign, stage, handler, task, result));
rv.casesDeltas.addAll(caseHelper.getDeltasToCreateCases(campaign, stage, handler, task, result));
} else {
rv.addAll(caseHelper.getDeltasToAdvanceCases(campaign, stage, task, result));
rv.casesDeltas.addAll(caseHelper.getDeltasToAdvanceCases(campaign, stage, task, result));
}

rv.add(createStageAddDelta(stage));
rv.addAll(createDeltasToRecordStageOpen(campaign, stage));
rv.addAll(createTriggersForTimedActions(campaign.getOid(), 0,
rv.campaignDeltas.add(createStageAddDelta(stage));
rv.campaignDeltas.addAll(createDeltasToRecordStageOpen(campaign, stage));
rv.campaignDeltas.addAll(createTriggersForTimedActions(campaign.getOid(), 0,
XmlTypeConverter.toDate(stage.getStartTimestamp()), XmlTypeConverter.toDate(stage.getDeadline()),
CertCampaignTypeUtil.findStageDefinition(campaign, newStageNumber).getTimedActions()));

LOGGER.trace("getDeltasForStageOpen finishing, returning {} deltas:\n{}", rv.size(), DebugUtil.debugDumpLazily(rv));
LOGGER.trace("getDeltasForStageOpen finishing, returning {} cases deltas and {} campaign deltas:\n{}\n{}",
rv.casesDeltas.size(), rv.campaignDeltas.size(), DebugUtil.debugDumpLazily(rv.casesDeltas),
DebugUtil.debugDumpLazily(rv.campaignDeltas));
return rv;
}

// some bureaucracy... stage#, state, start time, triggers
List<ItemDelta<?,?>> createDeltasToRecordStageOpen(AccessCertificationCampaignType campaign,
AccessCertificationStageType newStage) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException {
private List<ItemDelta<?,?>> createDeltasToRecordStageOpen(AccessCertificationCampaignType campaign,
AccessCertificationStageType newStage) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException {

final List<ItemDelta<?,?>> itemDeltaList = new ArrayList<>();

Expand Down
Expand Up @@ -42,6 +42,7 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -102,6 +103,8 @@ public class CertificationManagerImpl implements CertificationManager {
public static final String OPERATION_GET_CAMPAIGN_STATISTICS = INTERFACE_DOT + "getCampaignStatistics";
public static final String OPERATION_CLEANUP_CAMPAIGNS = INTERFACE_DOT + "cleanupCampaigns";

private static final int CASES_DELTAS_BATCH_SIZE = 60; // there are 6 deltas for single case modification (TODO)

@Autowired private PrismContext prismContext;
@Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService;
@Autowired private ModelService modelService;
Expand Down Expand Up @@ -256,8 +259,13 @@ public void openNextStage(String campaignOid, int requestedStageNumber, Task tas
} else {
final CertificationHandler handler = findCertificationHandler(campaign);
final AccessCertificationStageType stage = updateHelper.createStage(campaign, currentStageNumber+1);
final List<ItemDelta<?,?>> deltas = updateHelper.getDeltasForStageOpen(campaign, stage, handler, task, result);
updateHelper.modifyObjectViaModel(AccessCertificationCampaignType.class, campaignOid, deltas, task, result);
final AccCertUpdateHelper.StageOpenDeltas deltas = updateHelper.getDeltasForStageOpen(campaign, stage, handler, task, result);
// TODO rollback in case of error
List<List<ItemDelta<?, ?>>> batches = ListUtils.partition(deltas.casesDeltas, CASES_DELTAS_BATCH_SIZE);
for (List<ItemDelta<?, ?>> batch : batches) {
updateHelper.modifyObjectViaModel(AccessCertificationCampaignType.class, campaignOid, batch, task, result);
}
updateHelper.modifyObjectViaModel(AccessCertificationCampaignType.class, campaignOid, deltas.campaignDeltas, task, result);
updateHelper.afterStageOpen(campaignOid, stage, task, result);
}
} catch (RuntimeException e) {
Expand Down

0 comments on commit f5e894a

Please sign in to comment.