applyPlan Command and Use Cases

Sepasoft MES Module Suite

Commands for Managing Changesets

Together, these commands provide a framework for maintaining data integrity during complex system updates.

Make sure to read through the Changeset workflow before attempting to use these commands: Changesets.

Commands for Applying 

system.mes.changeset.applyPlan()

Calls system.mes.changeset.reconcile(), and then returns an object with these fields:

public final List<UUID> order;
Ensures no changeset is applied before one of it's subsequent changesets.
public final Map<UUID, String> blocked;
public final List<String> errors;

Execution: Figure out what needs to be applied from the disk.

  • reconcile from disk,
  • compute the apply plan, and
  • execute the plan in the order returned.

Python
# All 4 of these are equivalent
system.mes.changeset.applyMissing(None)
system.mes.changeset.applyMissing("")
system.mes.changeset.applyMissingInOrder(None)
system.mes.changeset.applyMissingInOrder([])

system.mes.changeset.applyMissing(String csv)

Applies changesets in the order of the csv string, if the string is empty or null, it calls system.mes.changeset.applyPlan() and uses that plan.

system.mes.changeset.applyMissingInOrder(List<String>)

ApplyMissingInOrder takes a list of UUIDs instead of a csv. Same applies here, passing in null or an empty list will cause the method to call system.mes.changeset.applyPlan() and use that plan.

Both of these methods return an apply result, it has the following fields.

public final List<UUID> applied;
public final Map<UUID, String> failures;

Commands for Viewing

Next case: The disk storage system has been updated through some external mechanism. Now you want to be able to view the changesets without applying the changes. To do this, call listOpen or listClosed.
Python
log = system.util.getLogger('Debug Logger') 
system.mes.changeset.reconcile() 
closedChangesets = system.mes.changeset.listClosed() 
for cs in closedChangesets: 	
  if not cs.applied: 		
    log.info(str(cs.changesetUUID) + ' is not applied')

Commands for Checking for Errors Before Applying

system.util.getLogger

Ensure that all the changesets are in a good state, so I want to do a dry run and check for errors before applying, I'll use system.mes.changeset.applyPlan() and use the returned object to check for errors or to call applyMissingInOrder if not. Also add checks that there are no blocked changesets or general errors. A general error would be something like 'Multiple INITIAL changesets found' that isn't tied to one specific changeset. Items are blocked if their preceding changeset wasn't found.

Python
log = system.util.getLogger('Debug Logger')
# applyPlan will reconcile before computing the plan
plan = system.mes.changeset.applyPlan()
if not plan.errors.isEmpty():
	log.error('Plan cannot be applied because of errors:')
	for error in plan.errors:
		log.error(error)
	return

if not plan.blocked.isEmpty():
	log.error('Plan has changesets that are blocked:')
	for entry in plan.blocked.entrySet():
		uuid = entry.getKey()
		message = entry.getValue()
		log.warn(str(uuid) + ' is blocked fpr the following reason: ' + message)
	return

# No errors, no blocked changeset, apply
if not plan.order.isEmpty():
	results = system.mes.changeset.applyMissingInOrder(plan.order)
	if not results.failures.isEmpty():
		for entry in results.failutres.entrySet():
			uuid = entry.getKey()
			message = entry.getValue()
			log.error(str(uuid) + ' failed to apply for the following reason: ' + message)

External Sync: Reconcile and View

Useful when changesets are moved to the disk via external tools (like Git or file transfer) and you want to see them in the UI without applying them yet.

Python
log = system.util.getLogger('ChangesetLogger')
# Scans disk and updates DB metadata
system.mes.changeset.reconcile()

# Now listClosed will include the newly discovered changesets
closedChangesets = system.mes.changeset.listClosed()
for cs in closedChangesets:
    if not cs.applied:
        log.info(str(cs.changesetUUID) + ' is ready to be applied')

Dry Run with Validation (Standard Pattern)

Before applying, check for "Blocked" changesets (missing dependencies) or "Errors" (like multiple initial changesets).

Python
log = system.util.getLogger('ChangesetLogger')

# applyPlan performs reconcile() internally
plan = system.mes.changeset.applyPlan()

if not plan.errors.isEmpty():
    log.error('Plan cannot be applied because of critical errors:')
    for error in plan.errors:
        log.error(error)
    return

if not plan.blocked.isEmpty():
    log.error('The following changesets are blocked (missing dependencies):')
    for uuid, reason in plan.blocked.items():
        log.warn(str(uuid) + ' is blocked for the following reason: ' + reason)
    return

# No errors or blocks, proceed with application
if not plan.order.isEmpty():
    results = system.mes.changeset.applyMissingInOrder(plan.order)
    if not results.failures.isEmpty():
        for uuid, error in results.failures.items():
            log.error(str(uuid) + ' failed to apply: ' + error)
    else:
        log.info('Successfully applied ' + str(len(results.applied)) + ' changesets.')

Safe Deploy Workflow

This snippet demonstrates a "Safe Deploy" workflow:

  1. Reconcile: Ensure we see what's on disk.

  2. Apply Plan: Check the order and dependencies.

  3. Apply Missing: Execute the plan.

Python
log = system.util.getLogger('ChangesetLogger')

# 1. Compute the application plan (applyPlan will reconcile first)
plan = system.mes.changeset.applyPlan()

# If we have a valid order and no blocks, we apply
if not plan.order.isEmpty() and plan.blocked.isEmpty():
    log.info("Applying " + str(len(plan.order)) + " changesets in dependency order...")
    
    # 2. Apply the specific plan we just validated
    results = system.mes.changeset.applyMissingInOrder(plan.order)
    
    log.info("Applied: " + str(results.applied))
    if not results.failures.isEmpty():
        log.error("Failures: " + str(results.failures))
else:
    if not plan.blocked.isEmpty():
        log.warn("Deployment aborted: some changesets are missing their predecessors.")
    else:

Sepasoft MES Module Suite