Class InsertionFilter<T extends InsertionFilterConfig>

java.lang.Object
com.tccc.kos.ext.dispense.service.insertion.InsertionFilter<T>
All Implemented Interfaces:
com.tccc.kos.commons.core.service.config.ConfigAware<T>, com.tccc.kos.commons.core.service.handle.HandleAware
Direct Known Subclasses:
IngredientFilter

public abstract class InsertionFilter<T extends InsertionFilterConfig> extends Object implements com.tccc.kos.commons.core.service.config.ConfigAware<T>
Base class for adding checks during the container insertion process. A filter can add troubles to block the insertion process until the troubles are resolved or the container is removed.

An individual request can be submitted to a filter many times based on overall system events and will remain in the pending insertion list until removed or successfully inserted into all associated pumps, even if some pumps have been successfully inserted.

While is is common to insert a container with a single ingredient (single ContainerSlice, into a single holder with a single pump, in some architectures it is possible to insert a multi-ingredient container into multiple holders, each with multiple pumps connected different nozzles. This leads to a two step check process for insertions.

The first step is a global check of the InsertRequest. Any block on this will prevent an pump level insertion checks. For example a filter may mark the container expired in which case the pumps have no need to be processed.

The second step is a check of each (@code InsertPumpRequest). There will be an individual request for each pump the container will be connected to. So long as the InsertRequest doesn't block, each InsertPumpRequest is considered an independent insertion and a single pump can be successfully inserted and used while other pumps remain blocked. An example of a pump-level block might be the need to prime the pump with the new container. If only one pump is primed, that pump can be used while the others are still blocked waiting for a prime of that particular line.

If a pump level check can block the entire request (such as an incompatible ingredient being inserted) then this block should be applied at the container / holder level in the InsertRequest to ensure that the request never progresses to the pump level checks.

The filter can attach data to the InsertRequest for use across multiple calls or between InsertRequest / InsertPumpRequest callbacks which allows for easy state sharing in the filter while still supporting multiple concurrent insertion requests. This allows the filter to have fine grained control over the insertion policy.

The filter process is two distinct phases. The first phase is the InsertRequest phase which considers the insertion as a whole and would factor in checks such as expired ingredients, sold out containers, etc... The second phase, which is only triggered after all the first phase checks pass, is the InsertPumpRequest phase, and is responsible for per-pump checks as described above. Once the InsertRequest phase passes, it will not be called again for a given insertion. Depending on the use case of the filter, this can greatly simplify the state machine of the filter.

Any troubles used in pump level blocks should extend PumpTroubleIface which will include the pump and nozzle holder paths in the trouble. This ensures that ui code can properly visualize things. For example, consider a dispenser with two heads (one screen / nozzle per head) where a pump for each head is attached to a single holder. If the pumps need to be primed, each head will need to be primed individually to ensure no consumer is in front of the head during the prime. This implies that one head can be healthy while the other is blocked. To visualize this, the troubles will need to be tagged by nozzle so the heads can filter out troubles for nozzle on the other head.

Filters are called in the order they are added to the service. The checkRequest() callback will be called on each retry until it passes without a block. After this checkPumpRequest will be called with each remaining pump until all pumps are inserted or the container is removed.

Every filter has a position and group property which is a decimal number. When adding a filter to the service, by default it will be added to the 0.0 group at the next available position (appended to the 0.0 group). It's possible to define a new group or specifically provide a position to allow a filter to be inserted between existing filters. Filters are ultimately sorted by group and then position in the group.

Since:
1.0
Version:
2023-01-30
  • Constructor Summary

    Constructors
    Constructor
    Description
    Create a filter with the specified name.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Called to verify if an InsertPumpRequest can be inserted.
    abstract void
    Called to verify if an InsertRequest can be inserted.
     
    double
    Return the group the filter was placed in within the filter chain.
    com.tccc.kos.commons.core.service.handle.Handle
     
    double
    Return the position the filter was placed in within the filter chain group.
    void
    setConfig(T config)
     
    void
    setHandle(com.tccc.kos.commons.core.service.handle.Handle handle)
     

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.tccc.kos.commons.core.service.config.ConfigAware

    onConfigChanged, onConfigSet

    Methods inherited from interface com.tccc.kos.commons.core.service.handle.HandleAware

    addHandleChild, getName, getPath
  • Constructor Details

    • InsertionFilter

      public InsertionFilter(String name)
      Create a filter with the specified name.
      Parameters:
      name - the name of the filter
  • Method Details

    • checkRequest

      public abstract void checkRequest(InsertRequest request)
      Called to verify if an InsertRequest can be inserted. Use request.block() to prevent the request from proceeding. To attach a trouble to the request but still allow the request to move forward, use request.warn() .
      Parameters:
      request - the request to operate on
    • checkPumpRequest

      public void checkPumpRequest(InsertPumpRequest request)
      Called to verify if an InsertPumpRequest can be inserted. This will be called once all filters pass checkRequest() . This allows pump level checks to be performed, where a single insert may impact multiple pumps independently.

      For example, consider an insertion that checks expiration date of the container and also requires a purge for each pump. The expiration is a container level check so it would be validated at the InsertReqeust level in checkRequest() . If this validation passes, there is then a need to purge each associated pump. As this is a per-pump requirement, this is validated using checkPumpRequest() as it is a check that needs to be performed per-pump and shouldn't be run if the container is expired.

      Use request.block() to prevent the request from proceeding. To attach a trouble to the request but still allow the request to move forward, use request.warn() . Override as needed.

      Parameters:
      request - the request to operate on
    • getGroup

      public double getGroup()
      Return the group the filter was placed in within the filter chain.
    • getPosition

      public double getPosition()
      Return the position the filter was placed in within the filter chain group.
    • getConfig

      public T getConfig()
      Specified by:
      getConfig in interface com.tccc.kos.commons.core.service.config.ConfigAware<T extends InsertionFilterConfig>
    • setConfig

      public void setConfig(T config)
      Specified by:
      setConfig in interface com.tccc.kos.commons.core.service.config.ConfigAware<T extends InsertionFilterConfig>
    • getHandle

      public com.tccc.kos.commons.core.service.handle.Handle getHandle()
      Specified by:
      getHandle in interface com.tccc.kos.commons.core.service.handle.HandleAware
    • setHandle

      public void setHandle(com.tccc.kos.commons.core.service.handle.Handle handle)