Class UsageService

java.lang.Object
ai.chatur.cortex.core.usage.UsageService

public class UsageService extends Object
Counts how often each resource is deliberately viewed, and turns those counts into a search ranking weight that fades as views age.

Only deliberate views are counted — opening a resource, not merely appearing in a result list. Counting search impressions would boost whatever already ranked highly, which is self-fulfilling and accelerates the feedback loop described below.

Counts live in the usage graph of the assertions dataset, a reserved named graph alongside provenance. Writing there does not touch the default graph, so the rule that approved assertions are only ever reached through review still holds.

Views decay with age. The stored value is not a tally but a score halved every halfLife, so what the graph's users consult *now* outranks what was popular a year ago. Rather than keeping a timestamped event per view — which would grow without bound — each resource keeps one score and the instant it was last brought up to date; the discount is applied on read and folded in on write. Changing the half-life therefore takes effect immediately, with no stored history to migrate. A half-life of zero disables decay, making the score a plain tally.

Views are not written as they happen. TDB2 admits a single writer, so a write transaction per view would serialize the read path against ingestion. Views accumulate in memory and are flushed in batches; a crash loses at most FLUSH_THRESHOLD views, which is immaterial for a relevance signal.

Only the unflushed deltas are held in memory — never the totals. A restore replaces the whole assertions dataset partway through startup, and a cached total captured before that would be written back over the restored counts on the next flush. Reading the current value inside the flush transaction makes the update a true increment and sidesteps the ordering entirely.

  • Constructor Details

    • UsageService

      public UsageService(org.apache.jena.query.Dataset assertions, Duration halfLife)
      Creates the service using the system clock.
      Parameters:
      assertions - the dataset whose usage graph holds the counts
      halfLife - how long it takes a view's contribution to lose half its weight; zero or negative disables decay, making the score a plain tally
    • UsageService

      public UsageService(org.apache.jena.query.Dataset assertions, Duration halfLife, Clock clock)
      Creates the service with an explicit clock.
      Parameters:
      assertions - the dataset whose usage graph holds the counts
      halfLife - how long it takes a view's contribution to lose half its weight; zero or negative disables decay, making the score a plain tally
      clock - the source of the current time, which decay is measured against
  • Method Details

    • recordView

      public void recordView(String uri)
      Records that a resource was deliberately viewed.

      Buffered in memory, and flushed once FLUSH_THRESHOLD views have accumulated. Must not be called from inside a transaction: a flush opens its own write transaction.

      Parameters:
      uri - the URI of the viewed resource
    • flush

      public void flush()
      Writes the buffered views to the usage graph in a single write transaction.

      Each score is re-read, decayed to the present, and incremented within that transaction, so concurrent writers and a restore that replaced the dataset are both accounted for. Safe to call when nothing is pending.

    • weights

      public Map<String,Double> weights(Collection<String> uris)
      Returns the ranking weight of each of the given resources.

      The weight saturates, so popularity nudges the ranking rather than dictating it: a resource nobody has opened scores 1.0 and no resource, however popular, exceeds 1 + MAX_BOOST. Scores are decayed to the present before weighting, so a resource that was popular long ago and has not been opened since ranks as though it were not.

      Parameters:
      uris - the resource URIs to weight
      Returns:
      the weight per URI, 1.0 for anything never viewed
    • viewScore

      public double viewScore(String uri)
      Returns a resource's decayed view score, including views not yet flushed.

      Equal to the number of views only when decay is disabled or no time has passed; otherwise older views contribute less than newer ones.

      Parameters:
      uri - the resource URI
      Returns:
      the decayed score, zero if the resource has never been viewed