Ledger queries

Feeds

Feeds allow you to sequentially process actions and transactions as they are added to a ledger, without the need for polling or keeping state in your application. This is helpful for:

On this page
  • Real-time applications, such as notifications or live-updating interfaces
  • Microservice architectures, where one service creates transactions and another service performs some operation in response

A feed is also how a system built around the ledger keeps its own state. The ledger records what happened and in what order; a service reads that order, applies its own logic to each item, and maintains whatever local state it needs — a reporting database, a compliance check, an instruction to an external system. Several services can each hold their own feed over the same ledger and arrive at consistent conclusions, because they are all reading the same sequence.

Order of itemsLink to this section

A feed provides items in chronological order, starting at the time the feed is created. (This is different from listing actions and transactions, which provides items in reverse chronological order.)

EfficiencyLink to this section

Under the hood, the SDK reads data from a feed using a long-polling mechanism. This ensures that network round trips between your application and Onyx Mesh are kept to a minimum.

At-least-once-deliveryLink to this section

Transaction feeds provide at-least-once delivery of items; occasionally, an item may be delivered multiple times. Regardless of how frequently you acknowledge, it’s a good idea to design your feed processing to be idempotent, so that your application can process a given item twice or more without adverse effects.

ConcurrencyLink to this section

Reading from a transaction feed may block your active process, so if your application does more than just consume a transaction feed, you should run the processing loop in its own thread.

In general, you should consume a transaction feed in one and only one thread. In particular, you’ll want to make sure that next and ack are called serially, within a single thread.

Data StructureLink to this section

Field DescriptionsLink to this section

FieldTypeDescription
typestringThe type of feed – action or transaction.
idstringUser-supplied or system-assigned unique identifier of the feed.
filterstringThe filter that determines which items get returned in the feed.
filter paramsarray of strings or intsThe ordered set of values for any placeholders (e.g $1) included in the filter.
cursorstringA pointer to the the last item acknowledged in the feed.

Example ObjectLink to this section

{
  type: "",
  id: "",
  filter: "",
  filterParams: [],
  cursor: ""
}
{
  type: "",
  id: "",
  filter: "",
  filterParams: [],
  cursor: ""
}
{
  type: "",
  id: "",
  filter: "",
  filter_params: [""],
  cursor: ""
}

ExamplesLink to this section

Create a feedLink to this section

Feeds are created from your application. When creating a feed, you can provide a filter so that the feed only returns items matching the filter. If you don’t supply a filter, the feed will return all new items (transactions or actions) as they are added to the ledger.

Feed<Action> feed = new Feed.Action.Builder()
  .setId("issuances")
  .setFilter("type=$1")
  .addFilterParameter("issue")
  .create(ledger);
let feed = await ledger.feeds.create({
  type: 'action',
  id: 'issuances',
  filter: 'type=$1',
  filterParams: ['issue']
})
feed = ledger.feeds.create(
  type: 'action',
  id: 'issuances',
  filter: 'type=$1',
  filterParams: ['issue']
)

Process a feedLink to this section

// Get feed
Feed<Action> feed = Feed.Action.get("issuances", ledger);

//Process feed item
for (Action action : feed) {
  // do something here to process the action in your application
  feed.ack();
}
// Get feed
let feed = await ledger.feeds.get(id: 'issuances')

// Process feed item
while (true) {
  let { value: action } = await feed.next()
  // do something here to process the action in your application
  await feed.ack()
}
# Get feed
feed = ledger.feeds.get(id: 'issuances')

# Process feed item
feed.consume do |action|
  # do something here to process the action in your application
  feed.ack
end