Interface AttributeSubscription

All Superinterfaces:
VersionedDataSource<AttributeSubscriptionUpdate>

@PublicApi public interface AttributeSubscription extends VersionedDataSource<AttributeSubscriptionUpdate>

AttributeSubscription represents an interest of the client code in a particular set of attribute values, allowing for background loading. It acts as a buffer, collecting the loaded values and serving it to the client as a VersionedDataSource.

Defining the value set

To indicate interest in a particular set of values, you need to set the forest spec, row set and attribute set via changeSubscription(java.util.function.Consumer<com.almworks.jira.structure.api.attribute.subscription.AttributeSubscriptionPatch>) method. You can later update the subscription by changing either of these parameters. The buffer will be cleared and adjusted accordingly. Any background loading that is no longer required will be automatically canceled.

Note that if you have interest in multiple sets (for example, in different forests, or different attributes for different rows), you need to create different subscriptions, rather than constantly adjusting a single subscription.

Access and permissions

The subscription uses the public methods of StructureAttributeService to load values. All values will be loaded according to the user's permissions and attribute sensitivity settings.

There's no way to create a subscription that overloads security.

Loading values

Note that the values will only be loaded when you call loadValues(). When to call this method is up to you, and you can call it any time. There's no reason to throttle the calls to loadValues(), it will happen on its own inside the subscription.

If you never call loadValues(), you will never receive any data!

See Also:
  • Method Details

    • getSubscriptionId

      long getSubscriptionId()
      Returns the ID of the subscription.
      Returns:
      subscription ID
      See Also:
    • changeSubscription

      void changeSubscription(@NotNull Consumer<AttributeSubscriptionPatch> changer)
      Updates the current subscription. The parts of the internal buffer that are no longer of interest will be cleared. If there is any background process loading values that are no longer needed, it will be canceled.
      Parameters:
      changer - the code that will update the subscription
    • getForest

      @NotNull ForestSpec getForest()
      Returns the forest spec currently set in this subscription. When the subscription is just created, returns an unspecified default forest spec.
      Returns:
      forest spec for subscribed values
    • getAttributes

      @NotNull Collection<AttributeSpec<?>> getAttributes()
      Returns the attributes that are currently subscribed for.
      Returns:
      attribute specs
    • getRows

      @NotNull LongList getRows()
      Returns the rows that are currently subscribed for.
      Returns:
      list of row ids
    • getUpdate

      @NotNull AttributeSubscriptionUpdate getUpdate(@NotNull DataVersion fromVersion)

      A quick, non-blocking retrieval of the updated values. Calling this method is guaranteed to return quickly, but there's no guarantee that all values will be up to date. Calling this method will not be blocked by attribute loading or generating the corresponding forest.

      Retrieving values from AttributeSubscription follows the Pull Architecture paradigm (see VersionedDataSource). The subscription acts as a buffer to contain the values loaded in the background. Once a value is loaded that is different from the one that was loaded for that attribute and row before, the version of this data source is promoted and the value is stored in a buffer. Requesting the values based on the previous version of the value update allows you to retrieve the values that were updated since the last call.

      When calling this method for the first time, use DataVersion.ZERO as the version.

      Specified by:
      getUpdate in interface VersionedDataSource<AttributeSubscriptionUpdate>
      Parameters:
      fromVersion - previous version of the data, received with a previous update
      Returns:
      an update based on the requested version
    • loadValues

      @NotNull CompletableFuture<DataVersion> loadValues()

      Requests that the subscription performs attribute loading.

      This will cause the subscription to start a background attribute loading process, based on the currently selected forest, rows and attributes. The method will return immediately, providing the caller with a Future. This Future may be waited upon to continue getting values via getUpdate(com.almworks.jira.structure.api.pull.DataVersion) once the loading is done.

      The implementation may limit how many processes can be started by a single subscription. If a call to loadValues() does not start a new background process, it will return the future from one of the already running processes.

      The returned future will be completed either with an updated version of the value update stream, or with an exception if there was a problem.

      The future may be canceled, which will cause the loading to cancel. However, the subscription will still be usable and any consequent calls to loadValues() will work.

      Returns:
      future version when everything is loaded and the buffer is updated
    • isLoadingValues

      boolean isLoadingValues()

      This method can be used to check if the attribute loading is currently taking place for this subscription.

      Returns:
      true if there's an active process of loading attributes
    • getFullUpdate

      @NotNull RowValues getFullUpdate(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
      Parameters:
      timeout - timeout value
      unit - timeout value units
      Returns:
      loaded values
      Throws:
      InterruptedException - if this thread was interrupted
      TimeoutException - if the values haven't finished loading in the specified time
    • getFullUpdate

      @NotNull RowValues getFullUpdate()

      A convenience method that loads all the values, waiting for them for an unspecified amount of time.

      Use with care! When writing code that backs a user interface, always use getFullUpdate(long, TimeUnit) with a short timeout and come back for updates later using getUpdate(DataVersion).

      Returns:
      loaded values
    • getInaccessibleRows

      @NotNull LongSet getInaccessibleRows()

      Returns the last known list of rows that are not accessible by the owner of the subscription.

      The rows may relate to a previous window (rows and forest), so it's not correct to make an assumption that all other rows are accessible. However, if there's data for a row, the row must have been accessible when the value was loaded.

      Returns:
      a list of inaccessible rows
    • drainAttributeErrors

      @NotNull Collection<AttributeErrorInfo> drainAttributeErrors()

      Retrieves accumulated information about attribute loader errors. Provides only new errors that happened after the last drain. Depending on the implementation strategy, may only return one error per attribute during the lifetime of the subscription.

      The accumulated list of errors is cleared when this method is called.

      Returns:
      the list of errors