com.almworks.jira.structure.api.row.RowManager Maven / Gradle / Ivy
Show all versions of structure-api Show documentation
package com.almworks.jira.structure.api.row;
import com.almworks.integers.*;
import com.almworks.jira.structure.api.forest.item.ItemForestBuilder;
import com.almworks.jira.structure.api.forest.raw.Forest;
import com.almworks.jira.structure.api.item.ItemIdentity;
import com.almworks.jira.structure.api.item.ItemIdentitySet;
import com.atlassian.annotations.Internal;
import com.atlassian.annotations.PublicApi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.function.LongConsumer;
import java.util.function.LongPredicate;
/**
* {@code RowManager} is responsible for maintaining row database and row properties.
*
* Rows are a core concept in Structure architecture. A forest contains rows, not items. Rows are inserted and
* moved around in the structure. However, rows are a technical concept -- the user deals with items. The main
* responsibility of this component is to maintain mapping between rows and items they contain.
*
* Rows are identified by their {@code long} ID. Anywhere where you need to store rows, you need to store
* its row ID -- you can later retrieve item ID from the {@code RowManager}.
*
* Rows are immutable. Once created, row information cannot be changed. Unused rows may be forgotten and later
* reused or removed from the database by Row Manager.
*
* Permanent and Transient Rows
*
* Rows can be permanent and transient. Transient rows are used by the generators for the dynamic content.
* As the content gets recalculated, new rows may be created, or the old ones may be reused.
*
* Transient rows live only in the JIRA instance's memory and not stored in the database. When JIRA restarts,
* all transient rows are lost.
*
* On JIRA Data Center, transient row only lives on the node where it was created.
* Another node will have its own version of that row, likely with a different row ID,
* as all generators will work on that node separately.
*
* Transient rows can also be created not by generators but by manual action when they need to be inserted
* into a transient forest source, such as a clipboard.
*
* Permanent rows are created for static structure content that is stored in the database. They are never
* deleted and not reused. In the coming version of Structure we will implement a "garbage collector" for
* the unused permanent rows.
*
* Temporary Rows
*
* Note: there may be negative row IDs that are used for temporary rows when building forest fragments —
* see {@link ItemForestBuilder}. Usage of these row ID must be confined to the builder they came from. Trying to
* retrieve rows with negative ID from {@code RowManager} would result in {@link MissingRowException}.
*
* @see StructureRow
*/
@PublicApi
public interface RowManager extends RowRetriever {
/**
* Creates a new persistent row for the given item ID and semantics.
*
* @param itemId item ID
* @param semantics semantics code. Semantics is still work in progress, and passing any value other
* than 0 may result in undefined behavior.
* @return row ID of the new row
*/
long createRow(@NotNull ItemIdentity itemId, long semantics);
/**
* Returns all rows created for the specified item.
*
* Note: although this method returns transient rows as well, it cannot be relied upon
* to find which dynamic structures contain a specific item, because a structure needs to be generated first.
*
* This method should be sufficiently fast, implementations should do indexing.
*
* This method will iterate through all the rows it finds before returning. If you want to stop scanning early,
* please use {@link #findRows(ItemIdentity, LongPredicate)} instead.
*
* @param itemId item ID
* @return an iterator that provides row IDs of permanent and transient rows that contain this item
*/
@NotNull
default LongIterator findRows(@Nullable ItemIdentity itemId) {
LongArray rows = new LongArray();
findRows(itemId, rows::add);
return rows.iterator();
}
/**
* Iterates through all rows created for the specified item.
*
* Note: although this method returns transient rows as well, it cannot be relied upon
* to find which dynamic structures contain a specific item, because a structure needs to be generated first.
*
* The {@code consumer} is called under a read lock, so it should be fast and take no locks.
*
* This method should be sufficiently fast, implementations should do indexing.
*
* @param itemId item ID
* @param consumer a consumer for found row IDs
*/
default void findRows(@Nullable ItemIdentity itemId, @NotNull LongConsumer consumer) {
findRows(itemId, i -> {
consumer.accept(i);
return true;
});
}
/**
* Iterates through all rows created for the specified item.
*
* Note: although this method returns transient rows as well, it cannot be relied upon
* to find which dynamic structures contain a specific item, because a structure needs to be generated first.
*
* The {@code consumer} is called under a read lock, so it should be fast and take no locks.
*
* This method should be sufficiently fast, implementations should do indexing.
*
* @param itemId item ID
* @param consumer a consumer for found row IDs; must return {@code true} to continue iteration, {@code false} to stop
*/
void findRows(@Nullable ItemIdentity itemId, @NotNull LongPredicate consumer);
/**
* Creates a mapper. {@code RowMapper} is needed when, for one or more rows, you need to find the very original
* row IDs.
*
* @param forest forest that contains candidate rows and generators
* @return a mapper
* @see RowMapper
*/
@Internal
@NotNull
RowMapper createMapper(@NotNull Forest forest);
@NotNull
@Override
default Set collectItemIds(@Nullable LongIterable rows) {
return ItemIdentitySet.collectItemIds(this, rows);
}
}