pub struct SqlStore { /* private fields */ }Expand description
Runlight’s tables in a database: everything recorded, and every report read from it.
Implementations§
Source§impl SqlStore
impl SqlStore
Sourcepub fn new(db: Arc<dyn Db>) -> SqlStore
pub fn new(db: Arc<dyn Db>) -> SqlStore
A store over a database, its tables named rl_ and something (or under the Db’s own prefix, for a
Prefixed one).
Sourcepub fn with_prefix(db: Arc<dyn Db>, prefix: &str) -> Result<SqlStore, DbError>
pub fn with_prefix(db: Arc<dyn Db>, prefix: &str) -> Result<SqlStore, DbError>
A store whose table and index names start with prefix in place of rl_, so two apps can each
keep Runlight’s tables in one database: up to 32 letters, digits, and underscores, not starting
with a digit. A Db that is already prefixed keeps its own.
Sourcepub fn prefix(&self) -> &str
pub fn prefix(&self) -> &str
What the store’s table and index names start with: rl_ unless it was given another.
Sourcepub fn tables(&self) -> Vec<String>
pub fn tables(&self) -> Vec<String>
The store’s tables as named in the database, for an app removing Runlight: each one by name, since another app’s tables may well start with the same letters.
Sourcepub async fn migrate(&self) -> Result<(), DbError>
pub async fn migrate(&self) -> Result<(), DbError>
Creates the tables on first use. Safe to call any number of times.
Sourcepub async fn optimize(&self, only_when_stale: bool)
pub async fn optimize(&self, only_when_stale: bool)
Keeps SQLite’s planner statistics current, which it never gathers by itself. A sample of each index is enough, so this takes a few seconds at most even on a large database. Postgres gathers its own.
With only_when_stale, only when there are none, or the events have more than doubled since they
were gathered. Statistics gathered on a new, empty database say every table is empty, and a goal
over a million visits then took a minute rather than milliseconds.
Sourcepub async fn transaction<T, F, Fut>(&self, f: F) -> Result<T, DbError>
pub async fn transaction<T, F, Fut>(&self, f: F) -> Result<T, DbError>
Runs f with a store whose every query is in one transaction.
Sourcepub async fn upsert_site(&self, site: &SiteRow, now: i64) -> Result<(), DbError>
pub async fn upsert_site(&self, site: &SiteRow, now: i64) -> Result<(), DbError>
Records a site, leaving an unchanged one alone, so starting needs no write.
Sourcepub async fn site_overrides(
&self,
) -> Result<HashMap<String, SiteOverrides>, DbError>
pub async fn site_overrides( &self, ) -> Result<HashMap<String, SiteOverrides>, DbError>
Settings changed in the dashboard, by site. They win over the ones in code.
Sourcepub async fn delete_site(&self, id: &str) -> Result<(), DbError>
pub async fn delete_site(&self, id: &str) -> Result<(), DbError>
Deletes a site and everything recorded for it. Its events and visits go a day at a time first, so a big site does not hold the database for minutes, and what is left goes in one transaction.
Sourcepub async fn drop_before(&self, site: &str, ts: i64) -> Result<(), DbError>
pub async fn drop_before(&self, site: &str, ts: i64) -> Result<(), DbError>
Deletes a site’s visits and events from before a time, for its retention setting.
Sourcepub async fn drop_orphans(
&self,
site: &str,
from: i64,
until: i64,
) -> Result<(), DbError>
pub async fn drop_orphans( &self, site: &str, from: i64, until: i64, ) -> Result<(), DbError>
Deletes a site’s events from from on whose visit no longer exists, a day at a time.
Sourcepub async fn build_rollup_day(
&self,
site: &str,
day: &str,
start: i64,
end: i64,
) -> Result<(), DbError>
pub async fn build_rollup_day( &self, site: &str, day: &str, start: i64, end: i64, ) -> Result<(), DbError>
Adds up one local day of a site: totals, each visit dimension, and pages. A visit belongs to the day it started. Visitor ids change every day, so the days of a range add up to exactly what counting the range would give.
Sourcepub async fn rollup_days(&self, site: &str) -> Result<HashSet<String>, DbError>
pub async fn rollup_days(&self, site: &str) -> Result<HashSet<String>, DbError>
The days of a site already built.
Sourcepub async fn clear_rollups(
&self,
site: &str,
before: Option<i64>,
between: Option<(i64, i64)>,
) -> Result<(), DbError>
pub async fn clear_rollups( &self, site: &str, before: Option<i64>, between: Option<(i64, i64)>, ) -> Result<(), DbError>
Forgets built days, all of a site’s (before and between both None), those starting before
a time, or those touching a stretch of time, so they are built again.
Sourcepub async fn set_site_overrides(
&self,
id: &str,
overrides: &SiteOverrides,
) -> Result<(), DbError>
pub async fn set_site_overrides( &self, id: &str, overrides: &SiteOverrides, ) -> Result<(), DbError>
Saves the settings changed in the dashboard for a site.
Sourcepub async fn last_seen(&self, site: &str) -> Result<Option<i64>, DbError>
pub async fn last_seen(&self, site: &str) -> Result<Option<i64>, DbError>
When the site last recorded a visit, or None if it never has.
Sourcepub async fn salt(&self, day: &str, fresh: &str) -> Result<String, DbError>
pub async fn salt(&self, day: &str, fresh: &str) -> Result<String, DbError>
The salt for a day, made on first ask. Two racing callers agree on one.
Sourcepub async fn salt_if_exists(&self, day: &str) -> Result<Option<String>, DbError>
pub async fn salt_if_exists(&self, day: &str) -> Result<Option<String>, DbError>
The salt for a day, if there is one.
Sourcepub async fn drop_salts_except(&self, days: &[String]) -> Result<(), DbError>
pub async fn drop_salts_except(&self, days: &[String]) -> Result<(), DbError>
Deletes every salt but those of these days, so the hashes made with them can never be made again.
Sourcepub async fn visit_open(
&self,
sites: &[String],
from: i64,
to: i64,
since: i64,
) -> Result<bool, DbError>
pub async fn visit_open( &self, sites: &[String], from: i64, to: i64, since: i64, ) -> Result<bool, DbError>
Whether a visit to one of these sites that started in a stretch of time was still going at since.
Sourcepub async fn open_session(
&self,
site: &str,
visitors: &[String],
since: i64,
) -> Result<Option<(String, String)>, DbError>
pub async fn open_session( &self, site: &str, visitors: &[String], since: i64, ) -> Result<Option<(String, String)>, DbError>
The visitor’s open session: any of their hashes, active since since.
Sourcepub async fn settle_open_session(
&self,
site: &str,
visitors: &[String],
since: i64,
opened: (String, String),
) -> Result<(String, String), DbError>
pub async fn settle_open_session( &self, site: &str, visitors: &[String], since: i64, opened: (String, String), ) -> Result<(String, String), DbError>
After opening a visit: the visitor’s earliest visit still going, which is this one unless another process opened one for the same visitor at the same moment. Then both settle on the earliest, and the one that is not drops its own, before anything is counted into it.
Sourcepub async fn insert_session(&self, row: &SessionRow) -> Result<(), DbError>
pub async fn insert_session(&self, row: &SessionRow) -> Result<(), DbError>
Records a new visit.
Sourcepub async fn touch_session(
&self,
id: &str,
ts: i64,
kind: &str,
path: &str,
reopen: bool,
) -> Result<(), DbError>
pub async fn touch_session( &self, id: &str, ts: i64, kind: &str, path: &str, reopen: bool, ) -> Result<(), DbError>
Counts a row into its session. An event with reopen false, one that joins a visit already
ended, counts without moving the session’s last activity.
Sourcepub async fn add_engagement(&self, id: &str, ms: i64) -> Result<(), DbError>
pub async fn add_engagement(&self, id: &str, ms: i64) -> Result<(), DbError>
Adds engaged time to a visit.
Sourcepub async fn pageview(
&self,
site: &str,
pageview: &str,
) -> Result<Option<PageviewInfo>, DbError>
pub async fn pageview( &self, site: &str, pageview: &str, ) -> Result<Option<PageviewInfo>, DbError>
The pageview an engagement ping or event belongs to, with when its visit started and was last active.
Sourcepub async fn touched_old_visit(
&self,
site: &str,
started: i64,
before: i64,
) -> Result<(), DbError>
pub async fn touched_old_visit( &self, site: &str, started: i64, before: i64, ) -> Result<(), DbError>
After a late event or engagement ping joins an old visit, the day that visit started may already be added up. Forget that day so the next check builds it again.
Sourcepub async fn link_by_slug(&self, slug: &str) -> Result<Option<LinkRow>, DbError>
pub async fn link_by_slug(&self, slug: &str) -> Result<Option<LinkRow>, DbError>
The live link with a slug. Slugs are unique across every domain.
Sourcepub async fn link_by_id(&self, id: &str) -> Result<Option<LinkRow>, DbError>
pub async fn link_by_id(&self, id: &str) -> Result<Option<LinkRow>, DbError>
The live link with an id.
Sourcepub async fn delete_link(&self, id: &str, now: i64) -> Result<(), DbError>
pub async fn delete_link(&self, id: &str, now: i64) -> Result<(), DbError>
Hides a link and frees its slug; its clicks stay in the history.
A site’s share links, newest first.
A share link by its id.
Records a share link.
Renames a share link.
Deleting a share is how it is revoked: the link stops working at once.
Sourcepub async fn funnels(&self, site: &str) -> Result<Vec<FunnelRow>, DbError>
pub async fn funnels(&self, site: &str) -> Result<Vec<FunnelRow>, DbError>
A site’s funnels, oldest first.
Sourcepub async fn save_funnel(&self, f: &FunnelRow) -> Result<(), DbError>
pub async fn save_funnel(&self, f: &FunnelRow) -> Result<(), DbError>
Records or changes a funnel.
Sourcepub fn funnel_visits(&self) -> i64
pub fn funnel_visits(&self) -> i64
The most visits a funnel is counted over: FUNNEL_VISITS unless a test lowered it.
Sourcepub async fn funnel_counts(
&self,
query: &Query,
funnel: &FunnelRow,
) -> Result<(Vec<f64>, bool), DbError>
pub async fn funnel_counts( &self, query: &Query, funnel: &FunnelRow, ) -> Result<(Vec<f64>, bool), DbError>
How many visits reached each step, in order, within the same visit, and whether only the newest
funnel_visits visits in the range were counted. Step one is the first matching
row in the range; each later step must come after the step before it.
Sourcepub async fn journey_pages(
&self,
query: &Query,
per_visit: i64,
) -> Result<(Vec<(String, String)>, bool), DbError>
pub async fn journey_pages( &self, query: &Query, per_visit: i64, ) -> Result<(Vec<(String, String)>, bool), DbError>
Each visit’s pageviews in order, at most per_visit of them, for journeys. A window function
keeps the first ones of each visit, so a long visit cannot crowd the rest out.
Sourcepub async fn token_by_hash(
&self,
hash: &str,
) -> Result<Option<TokenRow>, DbError>
pub async fn token_by_hash( &self, hash: &str, ) -> Result<Option<TokenRow>, DbError>
The token with this hash.
Sourcepub async fn touch_token(&self, id: &str, now: i64) -> Result<(), DbError>
pub async fn touch_token(&self, id: &str, now: i64) -> Result<(), DbError>
Notes when a token was last used.
Sourcepub async fn delete_token(&self, id: &str) -> Result<bool, DbError>
pub async fn delete_token(&self, id: &str) -> Result<bool, DbError>
Deleting a token is how it is revoked: it stops working at once.
Sourcepub async fn settings_starting_with(
&self,
prefix: &str,
) -> Result<Vec<(String, String)>, DbError>
pub async fn settings_starting_with( &self, prefix: &str, ) -> Result<Vec<(String, String)>, DbError>
Every setting whose key starts with a prefix, such as each connected install’s.
Sourcepub async fn take_setting(&self, key: &str) -> Result<Option<String>, DbError>
pub async fn take_setting(&self, key: &str) -> Result<Option<String>, DbError>
Reads a setting and deletes it. Of two callers at once, only the one whose delete took the row gets its value.
Sourcepub async fn add_setting(&self, key: &str, value: &str) -> Result<bool, DbError>
pub async fn add_setting(&self, key: &str, value: &str) -> Result<bool, DbError>
Writes a setting only if it is not there yet. Of two callers at once, only one gets true.
Sourcepub async fn swap_setting(
&self,
key: &str,
from: &str,
to: &str,
) -> Result<bool, DbError>
pub async fn swap_setting( &self, key: &str, from: &str, to: &str, ) -> Result<bool, DbError>
Changes a setting only if it still holds from. Of two callers at once, only one gets true.
Sourcepub async fn setting_or_add(
&self,
key: &str,
make: impl Fn() -> String,
) -> Result<String, DbError>
pub async fn setting_or_add( &self, key: &str, make: impl Fn() -> String, ) -> Result<String, DbError>
A setting that is made the first time it is asked for. Every caller gets the value written first, however many ask at once.
Sourcepub async fn set_setting(
&self,
key: &str,
value: Option<&str>,
) -> Result<(), DbError>
pub async fn set_setting( &self, key: &str, value: Option<&str>, ) -> Result<(), DbError>
Saves a setting, or deletes it with None.
Sourcepub async fn reports(
&self,
site: Option<&str>,
) -> Result<Vec<ReportRow>, DbError>
pub async fn reports( &self, site: Option<&str>, ) -> Result<Vec<ReportRow>, DbError>
Email reports, a site’s or all.
Sourcepub async fn report_by(
&self,
by_token: bool,
value: &str,
) -> Result<Option<ReportRow>, DbError>
pub async fn report_by( &self, by_token: bool, value: &str, ) -> Result<Option<ReportRow>, DbError>
A report by its id, or by its unsubscribe token.
Sourcepub async fn claim_report(
&self,
id: &str,
period: &str,
now: i64,
) -> Result<bool, DbError>
pub async fn claim_report( &self, id: &str, period: &str, now: i64, ) -> Result<bool, DbError>
Records a period as sent. Only one caller wins, so two cron runs at once cannot both send it.
Sourcepub async fn release_report(
&self,
id: &str,
period: &str,
previous: &str,
) -> Result<(), DbError>
pub async fn release_report( &self, id: &str, period: &str, previous: &str, ) -> Result<(), DbError>
Puts a period back when its email failed, so the next run tries again.
Sourcepub async fn goals(&self, site: Option<&str>) -> Result<Vec<GoalRow>, DbError>
pub async fn goals(&self, site: Option<&str>) -> Result<Vec<GoalRow>, DbError>
Goals, a site’s or all, oldest first.
Sourcepub async fn save_goal(
&self,
g: &GoalRow,
before: Option<&GoalRow>,
) -> Result<(), DbError>
pub async fn save_goal( &self, g: &GoalRow, before: Option<&GoalRow>, ) -> Result<(), DbError>
Records or changes a goal.
Sourcepub async fn event_prop_keys(
&self,
query: &Query,
event: &str,
) -> Result<Vec<(String, f64)>, DbError>
pub async fn event_prop_keys( &self, query: &Query, event: &str, ) -> Result<Vec<(String, f64)>, DbError>
The property names sent with an event in a query’s range, most used first.
Sourcepub async fn event_prop_values(
&self,
query: &Query,
event: &str,
key: &str,
limit: i64,
) -> Result<Vec<(String, f64, f64)>, DbError>
pub async fn event_prop_values( &self, query: &Query, event: &str, key: &str, limit: i64, ) -> Result<Vec<(String, f64, f64)>, DbError>
The values one property of an event took, with how often and by how many visitors.
Sourcepub async fn goal_totals_all(
&self,
query: &Query,
goals: &[GoalRow],
) -> Result<HashMap<String, GoalTotals>, DbError>
pub async fn goal_totals_all( &self, query: &Query, goals: &[GoalRow], ) -> Result<HashMap<String, GoalTotals>, DbError>
Every goal’s totals in one pass over the range’s events, instead of a query per goal.
Sourcepub async fn goal_totals(
&self,
query: &Query,
goal: &GoalRow,
) -> Result<GoalTotals, DbError>
pub async fn goal_totals( &self, query: &Query, goal: &GoalRow, ) -> Result<GoalTotals, DbError>
One goal’s conversions, converting visitors, and revenue for a query’s range and filters.
Sourcepub async fn goal_breakdown(
&self,
query: &Query,
goal: &GoalRow,
by: &str,
limit: i64,
) -> Result<Vec<(String, GoalTotals)>, DbError>
pub async fn goal_breakdown( &self, query: &Query, goal: &GoalRow, by: &str, limit: i64, ) -> Result<Vec<(String, GoalTotals)>, DbError>
A goal’s conversions split by where the visit came from, or by the page it happened on.
Sourcepub async fn goal_series(
&self,
site: &str,
filters: &[Filter],
goal: &GoalRow,
buckets: &[Bucket],
) -> Result<Vec<(i64, f64, f64)>, DbError>
pub async fn goal_series( &self, site: &str, filters: &[Filter], goal: &GoalRow, buckets: &[Bucket], ) -> Result<Vec<(i64, f64, f64)>, DbError>
A goal’s conversions and revenue in each bucket, by when each visit started.
Sourcepub async fn link_domains(&self) -> Result<Vec<(String, String)>, DbError>
pub async fn link_domains(&self) -> Result<Vec<(String, String)>, DbError>
Every link domain and its site.
Sourcepub async fn add_link_domain(
&self,
domain: &str,
site: &str,
now: i64,
) -> Result<(), DbError>
pub async fn add_link_domain( &self, domain: &str, site: &str, now: i64, ) -> Result<(), DbError>
Adds a link domain.
Sourcepub async fn remove_link_domain(&self, domain: &str) -> Result<(), DbError>
pub async fn remove_link_domain(&self, domain: &str) -> Result<(), DbError>
Removes a domain. Its links keep it as their home and fall back to the app’s own link path until the domain is added again.
Sourcepub async fn links(
&self,
site: &str,
from: i64,
to: i64,
) -> Result<Vec<(LinkRow, f64, f64)>, DbError>
pub async fn links( &self, site: &str, from: i64, to: i64, ) -> Result<Vec<(LinkRow, f64, f64)>, DbError>
A site’s links, newest first, with their clicks in a range. Clicks imported as daily counts have no visitor, so they add to clicks only.
Sourcepub async fn link_series(
&self,
site: &str,
link: &str,
buckets: &[Bucket],
) -> Result<Vec<(i64, f64, f64)>, DbError>
pub async fn link_series( &self, site: &str, link: &str, buckets: &[Bucket], ) -> Result<Vec<(i64, f64, f64)>, DbError>
One link’s clicks per bucket.
Sourcepub async fn link_breakdown(
&self,
site: &str,
link: &str,
from: i64,
to: i64,
dimension: &str,
limit: i64,
) -> Result<Vec<Value>, DbError>
pub async fn link_breakdown( &self, site: &str, link: &str, from: i64, to: i64, dimension: &str, limit: i64, ) -> Result<Vec<Value>, DbError>
One link’s clicks by a visit dimension.
Sourcepub async fn first_own_visit(&self, site: &str) -> Result<Option<i64>, DbError>
pub async fn first_own_visit(&self, site: &str) -> Result<Option<i64>, DbError>
When Runlight itself first counted a visit, leaving out imported history.
Sourcepub async fn first_seen(&self, site: &str) -> Result<Option<i64>, DbError>
pub async fn first_seen(&self, site: &str) -> Result<Option<i64>, DbError>
When the site’s first visit was recorded, or None with no data yet.
Sourcepub async fn visitors(&self, query: &Query) -> Result<f64, DbError>
pub async fn visitors(&self, query: &Query) -> Result<f64, DbError>
Just the visitor count from stats(), in one query, for conversion rates.
Sourcepub async fn series(
&self,
site: &str,
filters: &[Filter],
buckets: &[Bucket],
) -> Result<Vec<Value>, DbError>
pub async fn series( &self, site: &str, filters: &[Filter], buckets: &[Bucket], ) -> Result<Vec<Value>, DbError>
The chart: each bucket’s visitors, visits, pageviews, and the rest.
Sourcepub async fn hostname_suggestions(
&self,
query: &Query,
limit: i64,
) -> Result<Vec<Value>, DbError>
pub async fn hostname_suggestions( &self, query: &Query, limit: i64, ) -> Result<Vec<Value>, DbError>
A breakdown of a range by a dimension, a page of rows at a time. Seek one matching event per hostname, skipping its remaining events before the next seek.