MultiComponentFGC 2 (archived) - quality-manager/onboarding GitHub Wiki

Introduction

This is a continuation of the work that was suspended at the end of 2015. The idea is that we would have the ability to include multiple configurations of components into a single query scope, also known as an aggregate configuration. Working with Craig Chaney from JAF we had a prototype that allowed such configurations to be constructed. Queries would find artifacts across multiple configurations. When creating a new configuration aware item, the configuration of the component to which it belongs must be specified. For an explanation of what was accomplished prior to 2016 but not shipped see: MultiComponent FGC Phase 1

The expectation is that eventually, single-component FGC will be replaced by MultiComponent FGC. We do not envision this as yet another mode.

In QM 6.0.6 we are hoping to make progress on this feature, but we do not expect this to be in GA form. Perhaps we can have a technical preview.

For information on bringing up RQM in a mode that has MultiComponent FGC enabled see MultiComponent FGC Enablement

Terminology

Global Configuration

This is managed by the GC application.

Query Scope

This is a local copy of the parts of the GC that are relevant for operation. The query scope lives in the same database as QM, and QM code needs to join to it. We sometimes call it an aggregate configuration (and internally in the repository code it is currently implemented a configuration), but I think that is confusing terminology.

Component

This is the same as before. The only difference is that in single-component FGC, multiple components can be referenced in the GC, but only a single one can be active. So the "query scope" is a single configuration of a single component.

Configuration

This is the same as before, a baseline or stream of a component.

Global Configuration

The expectation is that the query scope will be defined using the global configuration application. This would most likely mean that FGC would require GC. However, the workings of this integration have not been agreed to and no implementation has yet begun. Frank believes that we need to keep a two-tier system where there is a separation of the GC definition from the query scope.

Internal ability to have local QM development without a GC application

We could consider allowing this for external users, but it would be most useful for QM development. This is similar to the way we can today run a development environment server without a JTS.

Support for delayed adoption of a GC change

A running QM service could not work reliably if the query scope changed underneath it. For example if the service was updating a test plan, and the query scope changed so that the test plan was not in it. For example if an adapter was executing a test case and the execution result is no longer in the query scope. For example if a PDF print had started but a referenced item is no longer in the query scope.

By having the query scope (aggregate configuration) as a separate entity from the GC, we can allow clean separation.

How to stage a change from a GC

When a GC changes the referenced QM configurations of components, the GC application can prevent component skew. But we may want to validate the versions of artifacts within the GC before the GC is propagated to the users. For example, it is conceivable that the artifacts in the GC have many broken references. These can only be validated by the QM application. It is conceivable that version skew could be automatically tested for by (and even avoided) by the GC app using a cache in the QM server, but there could still be a significant period of time where the validation is occurring. We presumably do not want to block all QM operations while this is going on.

We could have a pipeline where the GC changes are initiated, then validated, and then propagated. Once propagated, any new connection to the GC would access the new query scope, but existing connections would still use the older query scope that was already in use.

Removing old query scopes

Determining when the older query scope was no longer referenced would be non-trivial (QM has artifacts that store a reference to the configuration today, and this would reference a query scope).

Note that refactoring of an artifact across components can cause version skew in other query scopes that contain the target configuration of the refactoring operation. Similarly, a broken reference can arise in any query scope that contains the source configuration of the refactoring operation. In general, we can handle broken references but not version skew.

Functional components?

I think it may make sense to have specific functional components, and options to automatically select these components when an artifact is being created. For example, consider execution results. We could opt to simply put the execution result by default in the same component as its execution record. In work item FGC (MultiComponent) - startExecution needs to pass in componentUUID for test case execution result I at least partially implemented it this way for now. But it could be a nice feature to allow for options to specify at a project or team level where to put these results.

Similarly, when we create execution records, where should they go? We create this automatically if they do not exist, so we need to have an answer. Again, we could opt to put a TCER in the same component as its TestCase - but this might not be appropriate. For example, in one project the Test Cases may be managed by one team and test execution managed by another. So the person running a test may not have permission to create artifacts in a particular component.

Permissions and Process Area support for components and configurations

It would seem to make sense to have components and configurations logically belong to process areas. This way, we could have a team area for a component or configuration, and have edit permissions associated with the team rather than for every individual artifact.

Broken References

These can now occur anytime an artifact in the query scope references an artifact that is not in the query scope. We did an initial pass to paper over the ItemNotFoundExceptions and the like. However, we need to clean up the UI as we are not consistent in how we show missing information (Unassigned, blank, ...).

We should add some support for informing the user. A major use case would be for validating a query scope that is being constructed. We could also have more localized actions such as an action on the the browse page for test cases within a test plan to find the missing test cases (perhaps indicating the components/configurations where the artifact could be found.

In addition, there are special cases where we need to do more specific actions. For example, if you have a TCER with a missing script, you can still execute the TCER in a scriptless mode. However, it is currently an error to run a TCER where the TC cannot be found. I decided not to paper over that problem, as we need more of a design discussion. Should we simply refuse to run these in the UI, and disable the run actions? Should we flag these somehow? Should we consider hiding them in normal mode and excluding them from normal queries? I opened 168257: FGC (MultiComponent) - running a TCER where the TC is missing generates an error. for this.

Version Skew

Version skew would occur when the same configuration-aware item is in multiple sub configurations in the same query scope. If the versions are not the same, which version should be used for a query? If we need to update, which subconfiguration do we update?

For QM there is a worse problem in that our artifacts are made up of multiple items, and we could end up operating on a composite object where the items come from different components.

We need to prevent this, as the QM code does not handle this. QM should never operate in a query scope that has version skew, other than in a special mode to validate and repair the skew.

Can the same subconfiguration be active in multiple query scopes?

Assuming we have a staged approach to adopting changes in a GC it would be common to have the same subconfiguration active in multiple query scopes. Version skew prevention is more complicated in this case.

Imagine that we are moving (refactoring) an artifact from component A to component B within a query scope. There is no problem with this operation, as the artifact stays visible in the query scope and is in only a single component before and after the operation. But imagine that a different query scope contains the same configuration of component B and a different configuration of component A, and the artifact is in the configuration of component A. When we refactor the item, the different query scope would see the artifact in both component A and component B. We cannot allow this, so the refactor operation must fail.

This makes the problem of skew detection and prevention more difficult. It also raises the requirement level to be able to manage older query scopes to delete them as soon as possible.

Automatic version skew correction based on configuration ranking

This could be performed automatically by the repository code without product code (QM) being involved. Presumable the priority ordering described would come from GC.

Consider that a query does a join of a query table (eg TEST_CASE), a vtable (eg VTEST_CASE) and the query scope table that maps a query scope to a collection of subconfigurations. Imagine if the subconfigurations have a priority ordering, so that we resolve version skew by preferring the item from the configuration with higher priority. We could find the collection of items that have versions in multiple subconfigurations and create records in an exclusion table that combines the query scope UUID, the subconfiguration UUID, and the stateId of the item. When doing a query we would then also join to the exclusion table, and exclude those states.

This would complicate other operations such as refactor. We would probably also want to have tooling to allow trouble-shooting the skew and cleaning it up.

Refactor (move)

The current support for refactor is implemented as clone. We did this in RQM to be consistent with DNG and also because using move for refactor was not very useful in single-component FGC. So when we clone an artifact across components today, the artifact lives in both the source baseline and target stream.

With multiple components in a query scope, it makes more sense to move an artifact from one component to another within a query scope. To accomplish this, we would need the source to be a stream, which is not supported by IConfigurationManagementService.copyToStream(). So, we would need a new moveToStream approach which would take a source stream, target stream, and item. It would create a new vtable entry for the target, and a delete vtable entry for the source stream. We need to ensure transactional integrity for both the source and target streams.

Known issues

Methods not yet implemented by JAF

These throw exceptions with text "not yet implemented for fine grained components"

  • ConfigurationManagementService.copyItemState(IConfigurationHandle, IConfigurationHandle, IConfigurationAwareItemHandle)
  • ConfigurationManagementService.copyToStream(IConfigurationHandle, IConfigurationHandle, IItemHandle)
  • 49278: FGC (MultiComponent) - RepositoryItemService.getOriginalStreamForState() is not yet implemented
  • RepositoryItemService.getConfigurationsContainingItem(IConfigurationAwareItemHandle, boolean)
    • Used by
      • com.ibm.rqm.web.service.repair.RepairDatapoolVariableProblems.repair(RepairDuplicatedItems)
      • com.ibm.rqm.planning.service.internal.ManualExecutionScriptStepLookupService.findScriptStepLookupByScript_StateId(IManualExecutionScriptHandle, UUID)
        • This is used ALL OVER
  • RepositoryItemService.getConfigurationsForConfigurationQueryTypesContainingItem(IConfigurationAwareItemHandle, Set)
  • RepositoryItemService.getConfigurationsContainingItemHistory(IConfigurationAwareItemHandle, boolean)
  • RepositoryItemService.getConfigurationsForConfigurationQueryTypesContainingItemHistory(IConfigurationAwareItemHandle, Set)
  • RepositoryItemService.saveItemInCommonConfiguration(T)
  • RepositoryItemService.isStateInConfiguration(IConfigurationAwareItemHandle, IConfiguration)
  • RepositoryItemService.isStateExplicitlyInChangeSet(IConfigurationAwareItemHandle, IConfiguration)
  • RepositoryItemService.removeFromChangeSet(IConfigurationAwareItemHandle, IConfigurationHandle)

Things to explore with JAF (when Gary returns)