Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Index

A rewrite of my current laundry data that is better than storing API responses in a database. Actual tables created will increase in scope.

At a set interval, a program will collect laundry machine stats from the CSC API for a list of defined locations, and rooms. The program will insert into the Log table. Then constraints, checks, and other connections will ensure each location, room, and machine (possibly more) will appear in the correct table with complete information and relationships. In PG, timescale will ensure the LaundryLog table is optimized for time series data and provide extra functions to query the data.

Some queries can include a list of machines available or busy at room or location. How long has a machine been running, waiting to be emptied or free (Includes limit, see considerations). Provide useful insights including connecting to weather statistics to see usage change during seasons, how often a machine is used, and if a machine is likely to need maintenance (Counting run cycles).

Notes to self

  • Migrate from dbml file to generating from database.
2026-02-06 10:26:48 • commit: b3fc7f7

Architecture

Project Setup

Primary tooling is

Mise is for installing tools and managing run environments for all features. Docker runs mssql and postgres containers as needed for the program.

To start, set MISE_ENV to any of sqlite, postgres, mssql. Then run db:up, then app:run for debug.

Tasks

All mise tasks for each environment.

sqlite

Name         Description

app          Run app:build
app:build    Build app in release mode with only sqlite enabled
app:check    Check with clippy with only sqlite enabled
app:clean    Clean cargo build files
app:deps     Build a dependency tree using cargo
app:run      Run app with only sqlite enabled
db           Run db:up
db:clean     Clean left over database files
db:pre       Ran before db:up
docs         Runs docs:build
docs:build   Use MdBook to generate documentation
docs:clean   Cleans mdbook directories and generated assets
docs:render  Renders Schemas to an SVG
docs:serve   Uses MdBook to serve live documentation

postgres

Name         Description

app          Run app:build
app:build    Build app in release mode with only postgres enabled
app:check    Check with clippy with only postgres enabled
app:clean    Clean cargo build files
app:deps     Build a dependency tree using cargo
app:run      Run app with only postgres enabled
db           Run db:up
db:clean     Clean left over database files
db:down      Stop docker compose
db:logs      Check docker compose logs
db:pre       Ran before db:up
db:ps        Check running docker compose containers
db:up        Start docker compose
docs         Runs docs:build
docs:build   Use MdBook to generate documentation
docs:clean   Cleans mdbook directories and generated assets
docs:render  Renders Schemas to an SVG
docs:serve   Uses MdBook to serve live documentation

mssql

Name         Description

app          Run app:build
app:build    Build app in release mode with only mssql enabled
app:check    Check with clippy with only mssql enabled
app:clean    Clean cargo build files
app:deps     Build a dependency tree using cargo
app:run      Run app with only mssql enabled
db           Run db:up
db:clean     Clean left over database files
db:down      Stop docker compose
db:logs      Check docker compose logs
db:pre       Ran before db:up
db:ps        Check running docker compose containers
db:up        Start docker compose
docs         Runs docs:build
docs:build   Use MdBook to generate documentation
docs:clean   Cleans mdbook directories and generated assets
docs:render  Renders Schemas to an SVG
docs:serve   Uses MdBook to serve live documentation

Dependencies

sqlite

laundry-data v0.1.0 (/home/runner/work/laundry-data/laundry-data)
├── base64 v0.22.1
├── color-eyre v0.6.5
│   ├── backtrace v0.3.76
│   │   ├── addr2line v0.25.1
│   │   │   └── gimli v0.32.3
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   ├── miniz_oxide v0.8.9
│   │   │   ├── adler2 v2.0.1
│   │   │   └── simd-adler32 v0.3.8
│   │   ├── object v0.37.3
│   │   │   └── memchr v2.8.0
│   │   └── rustc-demangle v0.1.27
│   ├── color-spantrace v0.3.0
│   │   ├── once_cell v1.21.3
│   │   ├── owo-colors v4.2.3
│   │   ├── tracing-core v0.1.36
│   │   │   └── once_cell v1.21.3
│   │   └── tracing-error v0.2.1
│   │       ├── tracing v0.1.44
│   │       │   ├── pin-project-lite v0.2.16
│   │       │   ├── tracing-attributes v0.1.31 (proc-macro)
│   │       │   │   ├── proc-macro2 v1.0.106
│   │       │   │   │   └── unicode-ident v1.0.22
│   │       │   │   ├── quote v1.0.44
│   │       │   │   │   └── proc-macro2 v1.0.106 (*)
│   │       │   │   └── syn v2.0.114
│   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │       │   │       ├── quote v1.0.44 (*)
│   │       │   │       └── unicode-ident v1.0.22
│   │       │   └── tracing-core v0.1.36 (*)
│   │       └── tracing-subscriber v0.3.22
│   │           ├── matchers v0.2.0
│   │           │   └── regex-automata v0.4.14
│   │           │       ├── aho-corasick v1.1.4
│   │           │       │   └── memchr v2.8.0
│   │           │       ├── memchr v2.8.0
│   │           │       └── regex-syntax v0.8.9
│   │           ├── nu-ansi-term v0.50.3
│   │           ├── once_cell v1.21.3
│   │           ├── regex-automata v0.4.14 (*)
│   │           ├── serde v1.0.228
│   │           │   ├── serde_core v1.0.228
│   │           │   └── serde_derive v1.0.228 (proc-macro)
│   │           │       ├── proc-macro2 v1.0.106 (*)
│   │           │       ├── quote v1.0.44 (*)
│   │           │       └── syn v2.0.114 (*)
│   │           ├── serde_json v1.0.149
│   │           │   ├── itoa v1.0.17
│   │           │   ├── memchr v2.8.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── zmij v1.0.19
│   │           ├── sharded-slab v0.1.7
│   │           │   └── lazy_static v1.5.0
│   │           ├── smallvec v1.15.1
│   │           ├── thread_local v1.1.9
│   │           │   └── cfg-if v1.0.4
│   │           ├── time v0.3.47
│   │           │   ├── deranged v0.5.5
│   │           │   │   ├── powerfmt v0.2.0
│   │           │   │   └── serde_core v1.0.228
│   │           │   ├── itoa v1.0.17
│   │           │   ├── libc v0.2.180
│   │           │   ├── num-conv v0.2.0
│   │           │   ├── num_threads v0.1.7
│   │           │   ├── powerfmt v0.2.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── time-core v0.1.8
│   │           ├── tracing v0.1.44 (*)
│   │           ├── tracing-core v0.1.36 (*)
│   │           ├── tracing-log v0.2.0
│   │           │   ├── log v0.4.29
│   │           │   ├── once_cell v1.21.3
│   │           │   └── tracing-core v0.1.36 (*)
│   │           └── tracing-serde v0.2.0
│   │               ├── serde v1.0.228 (*)
│   │               └── tracing-core v0.1.36 (*)
│   ├── eyre v0.6.12
│   │   ├── indenter v0.3.4
│   │   └── once_cell v1.21.3
│   ├── indenter v0.3.4
│   ├── once_cell v1.21.3
│   ├── owo-colors v4.2.3
│   └── tracing-error v0.2.1 (*)
├── config v0.15.19
│   ├── convert_case v0.6.0
│   │   └── unicode-segmentation v1.12.0
│   ├── pathdiff v0.2.3
│   ├── serde_core v1.0.228
│   ├── serde_json v1.0.149 (*)
│   ├── toml v0.9.11+spec-1.1.0
│   │   ├── serde_core v1.0.228
│   │   ├── serde_spanned v1.0.4
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_datetime v0.7.5+spec-1.1.0
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_parser v1.0.6+spec-1.1.0
│   │   │   └── winnow v0.7.14
│   │   └── winnow v0.7.14
│   └── winnow v0.7.14
├── rand v0.10.0
│   ├── chacha20 v0.10.0
│   │   ├── cfg-if v1.0.4
│   │   ├── cpufeatures v0.3.0
│   │   └── rand_core v0.10.0
│   ├── getrandom v0.4.1
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   └── rand_core v0.10.0
│   └── rand_core v0.10.0
├── refinery v0.9.0
│   ├── refinery-core v0.9.0
│   │   ├── async-trait v0.1.89 (proc-macro)
│   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   ├── quote v1.0.44 (*)
│   │   │   └── syn v2.0.114 (*)
│   │   ├── cfg-if v1.0.4
│   │   ├── log v0.4.29
│   │   ├── regex v1.12.3
│   │   │   ├── aho-corasick v1.1.4 (*)
│   │   │   ├── memchr v2.8.0
│   │   │   ├── regex-automata v0.4.14 (*)
│   │   │   └── regex-syntax v0.8.9
│   │   ├── rusqlite v0.37.0
│   │   │   ├── bitflags v2.10.0
│   │   │   ├── fallible-iterator v0.3.0
│   │   │   ├── fallible-streaming-iterator v0.1.9
│   │   │   ├── hashlink v0.10.0
│   │   │   │   └── hashbrown v0.15.5
│   │   │   │       └── foldhash v0.1.5
│   │   │   ├── libsqlite3-sys v0.35.0
│   │   │   │   [build-dependencies]
│   │   │   │   ├── cc v1.2.55
│   │   │   │   │   ├── find-msvc-tools v0.1.9
│   │   │   │   │   ├── jobserver v0.1.34
│   │   │   │   │   │   └── libc v0.2.180
│   │   │   │   │   ├── libc v0.2.180
│   │   │   │   │   └── shlex v1.3.0
│   │   │   │   ├── pkg-config v0.3.32
│   │   │   │   └── vcpkg v0.2.15
│   │   │   └── smallvec v1.15.1
│   │   ├── serde v1.0.228 (*)
│   │   ├── siphasher v1.0.2
│   │   ├── thiserror v2.0.18
│   │   │   └── thiserror-impl v2.0.18 (proc-macro)
│   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │       ├── quote v1.0.44 (*)
│   │   │       └── syn v2.0.114 (*)
│   │   ├── time v0.3.47 (*)
│   │   ├── toml v0.8.23
│   │   │   ├── serde v1.0.228 (*)
│   │   │   ├── serde_spanned v0.6.9
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   ├── toml_datetime v0.6.11
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   └── toml_edit v0.22.27
│   │   │       ├── indexmap v2.13.0
│   │   │       │   ├── equivalent v1.0.2
│   │   │       │   └── hashbrown v0.16.1
│   │   │       ├── serde v1.0.228 (*)
│   │   │       ├── serde_spanned v0.6.9 (*)
│   │   │       ├── toml_datetime v0.6.11 (*)
│   │   │       ├── toml_write v0.1.2
│   │   │       └── winnow v0.7.14
│   │   ├── url v2.5.8
│   │   │   ├── form_urlencoded v1.2.2
│   │   │   │   └── percent-encoding v2.3.2
│   │   │   ├── idna v1.1.0
│   │   │   │   ├── idna_adapter v1.2.1
│   │   │   │   │   ├── icu_normalizer v2.1.1
│   │   │   │   │   │   ├── icu_collections v2.1.1
│   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro)
│   │   │   │   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │   │   │   │   ├── potential_utf v0.1.4
│   │   │   │   │   │   │   │   └── zerovec v0.11.5
│   │   │   │   │   │   │   │       ├── yoke v0.8.1
│   │   │   │   │   │   │   │       │   ├── stable_deref_trait v1.2.1
│   │   │   │   │   │   │   │       │   ├── yoke-derive v0.8.1 (proc-macro)
│   │   │   │   │   │   │   │       │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │   │   ├── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │   │   └── synstructure v0.13.2
│   │   │   │   │   │   │   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │   │       ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │   │       └── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │   └── zerofrom v0.1.6
│   │   │   │   │   │   │   │       │       └── zerofrom-derive v0.1.6 (proc-macro)
│   │   │   │   │   │   │   │       │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │           ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │           ├── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │           └── synstructure v0.13.2 (*)
│   │   │   │   │   │   │   │       ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   │       └── zerovec-derive v0.11.2 (proc-macro)
│   │   │   │   │   │   │   │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │           ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │           └── syn v2.0.114 (*)
│   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   ├── icu_normalizer_data v2.1.1
│   │   │   │   │   │   ├── icu_provider v2.1.1
│   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   ├── icu_locale_core v2.1.1
│   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   ├── litemap v0.8.1
│   │   │   │   │   │   │   │   ├── tinystr v0.8.2
│   │   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   │   │   ├── writeable v0.6.2
│   │   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   │   ├── writeable v0.6.2
│   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   ├── zerotrie v0.2.3
│   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   │   └── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   ├── smallvec v1.15.1
│   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   └── icu_properties v2.1.2
│   │   │   │   │       ├── icu_collections v2.1.1 (*)
│   │   │   │   │       ├── icu_locale_core v2.1.1 (*)
│   │   │   │   │       ├── icu_properties_data v2.1.2
│   │   │   │   │       ├── icu_provider v2.1.1 (*)
│   │   │   │   │       ├── zerotrie v0.2.3 (*)
│   │   │   │   │       └── zerovec v0.11.5 (*)
│   │   │   │   ├── smallvec v1.15.1
│   │   │   │   └── utf8_iter v1.0.4
│   │   │   └── percent-encoding v2.3.2
│   │   └── walkdir v2.5.0
│   │       └── same-file v1.0.6
│   └── refinery-macros v0.9.0 (proc-macro)
│       ├── heck v0.5.0
│       ├── proc-macro2 v1.0.106 (*)
│       ├── quote v1.0.44 (*)
│       ├── refinery-core v0.9.0
│       │   ├── async-trait v0.1.89 (proc-macro) (*)
│       │   ├── cfg-if v1.0.4
│       │   ├── log v0.4.29
│       │   ├── regex v1.12.3 (*)
│       │   ├── siphasher v1.0.2
│       │   ├── thiserror v2.0.18 (*)
│       │   ├── time v0.3.47
│       │   │   ├── deranged v0.5.5
│       │   │   │   └── powerfmt v0.2.0
│       │   │   ├── itoa v1.0.17
│       │   │   ├── num-conv v0.2.0
│       │   │   ├── powerfmt v0.2.0
│       │   │   └── time-core v0.1.8
│       │   ├── url v2.5.8 (*)
│       │   └── walkdir v2.5.0 (*)
│       ├── regex v1.12.3 (*)
│       └── syn v2.0.114 (*)
├── reqwest v0.13.2
│   ├── base64 v0.22.1
│   ├── bytes v1.11.1
│   ├── encoding_rs v0.8.35
│   │   └── cfg-if v1.0.4
│   ├── futures-core v0.3.31
│   ├── h2 v0.4.13
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── fnv v1.0.7
│   │   ├── futures-core v0.3.31
│   │   ├── futures-sink v0.3.31
│   │   ├── http v1.4.0
│   │   │   ├── bytes v1.11.1
│   │   │   └── itoa v1.0.17
│   │   ├── indexmap v2.13.0 (*)
│   │   ├── slab v0.4.12
│   │   ├── tokio v1.49.0
│   │   │   ├── bytes v1.11.1
│   │   │   ├── libc v0.2.180
│   │   │   ├── mio v1.1.0
│   │   │   │   └── libc v0.2.180
│   │   │   ├── parking_lot v0.12.5
│   │   │   │   ├── lock_api v0.4.14
│   │   │   │   │   └── scopeguard v1.2.0
│   │   │   │   └── parking_lot_core v0.9.12
│   │   │   │       ├── cfg-if v1.0.4
│   │   │   │       ├── libc v0.2.180
│   │   │   │       └── smallvec v1.15.1
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── signal-hook-registry v1.4.8
│   │   │   │   ├── errno v0.3.14
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   └── libc v0.2.180
│   │   │   ├── socket2 v0.6.1
│   │   │   │   └── libc v0.2.180
│   │   │   └── tokio-macros v2.6.0 (proc-macro)
│   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │       ├── quote v1.0.44 (*)
│   │   │       └── syn v2.0.114 (*)
│   │   ├── tokio-util v0.7.18
│   │   │   ├── bytes v1.11.1
│   │   │   ├── futures-core v0.3.31
│   │   │   ├── futures-io v0.3.31
│   │   │   ├── futures-sink v0.3.31
│   │   │   ├── futures-util v0.3.31
│   │   │   │   ├── futures-core v0.3.31
│   │   │   │   ├── futures-macro v0.3.31 (proc-macro)
│   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │   ├── futures-task v0.3.31
│   │   │   │   ├── pin-project-lite v0.2.16
│   │   │   │   ├── pin-utils v0.1.0
│   │   │   │   └── slab v0.4.12
│   │   │   ├── hashbrown v0.15.5 (*)
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── slab v0.4.12
│   │   │   └── tokio v1.49.0 (*)
│   │   └── tracing v0.1.44 (*)
│   ├── http v1.4.0 (*)
│   ├── http-body v1.0.1
│   │   ├── bytes v1.11.1
│   │   └── http v1.4.0 (*)
│   ├── http-body-util v0.1.3
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   └── pin-project-lite v0.2.16
│   ├── hyper v1.8.1
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── futures-channel v0.3.31
│   │   │   └── futures-core v0.3.31
│   │   ├── futures-core v0.3.31
│   │   ├── h2 v0.4.13 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── httparse v1.10.1
│   │   ├── itoa v1.0.17
│   │   ├── pin-project-lite v0.2.16
│   │   ├── pin-utils v0.1.0
│   │   ├── smallvec v1.15.1
│   │   ├── tokio v1.49.0 (*)
│   │   └── want v0.3.1
│   │       └── try-lock v0.2.5
│   ├── hyper-rustls v0.27.7
│   │   ├── http v1.4.0 (*)
│   │   ├── hyper v1.8.1 (*)
│   │   ├── hyper-util v0.1.20
│   │   │   ├── base64 v0.22.1
│   │   │   ├── bytes v1.11.1
│   │   │   ├── futures-channel v0.3.31 (*)
│   │   │   ├── futures-util v0.3.31 (*)
│   │   │   ├── http v1.4.0 (*)
│   │   │   ├── http-body v1.0.1 (*)
│   │   │   ├── hyper v1.8.1 (*)
│   │   │   ├── ipnet v2.11.0
│   │   │   ├── libc v0.2.180
│   │   │   ├── percent-encoding v2.3.2
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── socket2 v0.6.1 (*)
│   │   │   ├── tokio v1.49.0 (*)
│   │   │   ├── tower-service v0.3.3
│   │   │   └── tracing v0.1.44 (*)
│   │   ├── rustls v0.23.36
│   │   │   ├── aws-lc-rs v1.15.4
│   │   │   │   ├── aws-lc-sys v0.37.1
│   │   │   │   │   [build-dependencies]
│   │   │   │   │   ├── cc v1.2.55 (*)
│   │   │   │   │   ├── cmake v0.1.57
│   │   │   │   │   │   └── cc v1.2.55 (*)
│   │   │   │   │   ├── dunce v1.0.5
│   │   │   │   │   └── fs_extra v1.3.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── once_cell v1.21.3
│   │   │   ├── rustls-pki-types v1.14.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── rustls-webpki v0.103.9
│   │   │   │   ├── aws-lc-rs v1.15.4 (*)
│   │   │   │   ├── rustls-pki-types v1.14.0 (*)
│   │   │   │   └── untrusted v0.9.0
│   │   │   ├── subtle v2.6.1
│   │   │   └── zeroize v1.8.2
│   │   ├── rustls-pki-types v1.14.0 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-rustls v0.26.4
│   │   │   ├── rustls v0.23.36 (*)
│   │   │   └── tokio v1.49.0 (*)
│   │   └── tower-service v0.3.3
│   ├── hyper-util v0.1.20 (*)
│   ├── log v0.4.29
│   ├── mime v0.3.17
│   ├── percent-encoding v2.3.2
│   ├── pin-project-lite v0.2.16
│   ├── rustls v0.23.36 (*)
│   ├── rustls-pki-types v1.14.0 (*)
│   ├── rustls-platform-verifier v0.6.2
│   │   ├── log v0.4.29
│   │   ├── rustls v0.23.36 (*)
│   │   ├── rustls-native-certs v0.8.3
│   │   │   ├── openssl-probe v0.2.1
│   │   │   └── rustls-pki-types v1.14.0 (*)
│   │   └── rustls-webpki v0.103.9 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── serde_urlencoded v0.7.1
│   │   ├── form_urlencoded v1.2.2 (*)
│   │   ├── itoa v1.0.17
│   │   ├── ryu v1.0.23
│   │   └── serde v1.0.228 (*)
│   ├── sync_wrapper v1.0.2
│   │   └── futures-core v0.3.31
│   ├── tokio v1.49.0 (*)
│   ├── tokio-rustls v0.26.4 (*)
│   ├── tower v0.5.3
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── pin-project-lite v0.2.16
│   │   ├── sync_wrapper v1.0.2 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-http v0.6.8
│   │   ├── async-compression v0.4.39
│   │   │   ├── compression-codecs v0.4.36
│   │   │   │   ├── compression-core v0.4.31
│   │   │   │   ├── flate2 v1.1.5
│   │   │   │   │   ├── crc32fast v1.5.0
│   │   │   │   │   │   └── cfg-if v1.0.4
│   │   │   │   │   └── miniz_oxide v0.8.9 (*)
│   │   │   │   └── memchr v2.8.0
│   │   │   ├── compression-core v0.4.31
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   └── tokio v1.49.0 (*)
│   │   ├── bitflags v2.10.0
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── http-body-util v0.1.3 (*)
│   │   ├── iri-string v0.7.10
│   │   ├── pin-project-lite v0.2.16
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   ├── tower v0.5.3 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-service v0.3.3
│   └── url v2.5.8 (*)
├── serde v1.0.228 (*)
├── sql-middleware v0.6.0 (https://github.com/Stinky-c/sql-middleware?rev=950b044967bf652fbd483063b769619b7d1256c3#950b0449)
│   ├── async-trait v0.1.89 (proc-macro) (*)
│   ├── bb8 v0.9.1
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── parking_lot v0.12.5 (*)
│   │   └── tokio v1.49.0 (*)
│   ├── chrono v0.4.43
│   │   ├── iana-time-zone v0.1.65
│   │   ├── num-traits v0.2.19
│   │   │   [build-dependencies]
│   │   │   └── autocfg v1.5.0
│   │   └── serde v1.0.228 (*)
│   ├── clap v4.5.57
│   │   ├── clap_builder v4.5.57
│   │   │   ├── anstream v0.6.21
│   │   │   │   ├── anstyle v1.0.13
│   │   │   │   ├── anstyle-parse v0.2.7
│   │   │   │   │   └── utf8parse v0.2.2
│   │   │   │   ├── anstyle-query v1.1.5
│   │   │   │   ├── colorchoice v1.0.4
│   │   │   │   ├── is_terminal_polyfill v1.70.2
│   │   │   │   └── utf8parse v0.2.2
│   │   │   ├── anstyle v1.0.13
│   │   │   ├── clap_lex v0.7.7
│   │   │   └── strsim v0.11.1
│   │   └── clap_derive v4.5.55 (proc-macro)
│   │       ├── heck v0.5.0
│   │       ├── proc-macro2 v1.0.106 (*)
│   │       ├── quote v1.0.44 (*)
│   │       └── syn v2.0.114 (*)
│   ├── crossbeam-channel v0.5.15
│   │   └── crossbeam-utils v0.8.21
│   ├── deadpool v0.12.3
│   │   ├── deadpool-runtime v0.1.4
│   │   ├── lazy_static v1.5.0
│   │   ├── num_cpus v1.17.0
│   │   │   └── libc v0.2.180
│   │   └── tokio v1.49.0 (*)
│   ├── lazy_static v1.5.0
│   ├── parking_lot v0.12.5 (*)
│   ├── regex v1.12.3 (*)
│   ├── rusqlite v0.37.0 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── thiserror v2.0.18 (*)
│   ├── tokio v1.49.0 (*)
│   ├── tokio-util v0.7.18 (*)
│   └── tracing v0.1.44 (*)
├── tokio v1.49.0 (*)
├── tokio-util v0.7.18 (*)
├── tracing v0.1.44 (*)
├── tracing-subscriber v0.3.22 (*)
├── uuid v1.21.0
│   ├── getrandom v0.4.1 (*)
│   └── serde_core v1.0.228
└── xxhash-rust v0.8.15

postgres

laundry-data v0.1.0 (/home/runner/work/laundry-data/laundry-data)
├── base64 v0.22.1
├── color-eyre v0.6.5
│   ├── backtrace v0.3.76
│   │   ├── addr2line v0.25.1
│   │   │   └── gimli v0.32.3
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   ├── miniz_oxide v0.8.9
│   │   │   ├── adler2 v2.0.1
│   │   │   └── simd-adler32 v0.3.8
│   │   ├── object v0.37.3
│   │   │   └── memchr v2.8.0
│   │   └── rustc-demangle v0.1.27
│   ├── color-spantrace v0.3.0
│   │   ├── once_cell v1.21.3
│   │   ├── owo-colors v4.2.3
│   │   ├── tracing-core v0.1.36
│   │   │   └── once_cell v1.21.3
│   │   └── tracing-error v0.2.1
│   │       ├── tracing v0.1.44
│   │       │   ├── pin-project-lite v0.2.16
│   │       │   ├── tracing-attributes v0.1.31 (proc-macro)
│   │       │   │   ├── proc-macro2 v1.0.106
│   │       │   │   │   └── unicode-ident v1.0.22
│   │       │   │   ├── quote v1.0.44
│   │       │   │   │   └── proc-macro2 v1.0.106 (*)
│   │       │   │   └── syn v2.0.114
│   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │       │   │       ├── quote v1.0.44 (*)
│   │       │   │       └── unicode-ident v1.0.22
│   │       │   └── tracing-core v0.1.36 (*)
│   │       └── tracing-subscriber v0.3.22
│   │           ├── matchers v0.2.0
│   │           │   └── regex-automata v0.4.14
│   │           │       ├── aho-corasick v1.1.4
│   │           │       │   └── memchr v2.8.0
│   │           │       ├── memchr v2.8.0
│   │           │       └── regex-syntax v0.8.9
│   │           ├── nu-ansi-term v0.50.3
│   │           ├── once_cell v1.21.3
│   │           ├── regex-automata v0.4.14 (*)
│   │           ├── serde v1.0.228
│   │           │   ├── serde_core v1.0.228
│   │           │   └── serde_derive v1.0.228 (proc-macro)
│   │           │       ├── proc-macro2 v1.0.106 (*)
│   │           │       ├── quote v1.0.44 (*)
│   │           │       └── syn v2.0.114 (*)
│   │           ├── serde_json v1.0.149
│   │           │   ├── itoa v1.0.17
│   │           │   ├── memchr v2.8.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── zmij v1.0.19
│   │           ├── sharded-slab v0.1.7
│   │           │   └── lazy_static v1.5.0
│   │           ├── smallvec v1.15.1
│   │           ├── thread_local v1.1.9
│   │           │   └── cfg-if v1.0.4
│   │           ├── time v0.3.47
│   │           │   ├── deranged v0.5.5
│   │           │   │   ├── powerfmt v0.2.0
│   │           │   │   └── serde_core v1.0.228
│   │           │   ├── itoa v1.0.17
│   │           │   ├── libc v0.2.180
│   │           │   ├── num-conv v0.2.0
│   │           │   ├── num_threads v0.1.7
│   │           │   ├── powerfmt v0.2.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── time-core v0.1.8
│   │           ├── tracing v0.1.44 (*)
│   │           ├── tracing-core v0.1.36 (*)
│   │           ├── tracing-log v0.2.0
│   │           │   ├── log v0.4.29
│   │           │   ├── once_cell v1.21.3
│   │           │   └── tracing-core v0.1.36 (*)
│   │           └── tracing-serde v0.2.0
│   │               ├── serde v1.0.228 (*)
│   │               └── tracing-core v0.1.36 (*)
│   ├── eyre v0.6.12
│   │   ├── indenter v0.3.4
│   │   └── once_cell v1.21.3
│   ├── indenter v0.3.4
│   ├── once_cell v1.21.3
│   ├── owo-colors v4.2.3
│   └── tracing-error v0.2.1 (*)
├── config v0.15.19
│   ├── convert_case v0.6.0
│   │   └── unicode-segmentation v1.12.0
│   ├── pathdiff v0.2.3
│   ├── serde_core v1.0.228
│   ├── serde_json v1.0.149 (*)
│   ├── toml v0.9.11+spec-1.1.0
│   │   ├── serde_core v1.0.228
│   │   ├── serde_spanned v1.0.4
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_datetime v0.7.5+spec-1.1.0
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_parser v1.0.6+spec-1.1.0
│   │   │   └── winnow v0.7.14
│   │   └── winnow v0.7.14
│   └── winnow v0.7.14
├── rand v0.10.0
│   ├── chacha20 v0.10.0
│   │   ├── cfg-if v1.0.4
│   │   ├── cpufeatures v0.3.0
│   │   └── rand_core v0.10.0
│   ├── getrandom v0.4.1
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   └── rand_core v0.10.0
│   └── rand_core v0.10.0
├── refinery v0.9.0
│   ├── refinery-core v0.9.0
│   │   ├── async-trait v0.1.89 (proc-macro)
│   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   ├── quote v1.0.44 (*)
│   │   │   └── syn v2.0.114 (*)
│   │   ├── cfg-if v1.0.4
│   │   ├── log v0.4.29
│   │   ├── native-tls v0.2.14
│   │   │   ├── log v0.4.29
│   │   │   ├── openssl v0.10.75
│   │   │   │   ├── bitflags v2.10.0
│   │   │   │   ├── cfg-if v1.0.4
│   │   │   │   ├── foreign-types v0.3.2
│   │   │   │   │   └── foreign-types-shared v0.1.1
│   │   │   │   ├── libc v0.2.180
│   │   │   │   ├── once_cell v1.21.3
│   │   │   │   ├── openssl-macros v0.1.1 (proc-macro)
│   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │   └── openssl-sys v0.9.111
│   │   │   │       └── libc v0.2.180
│   │   │   │       [build-dependencies]
│   │   │   │       ├── cc v1.2.55
│   │   │   │       │   ├── find-msvc-tools v0.1.9
│   │   │   │       │   ├── jobserver v0.1.34
│   │   │   │       │   │   └── libc v0.2.180
│   │   │   │       │   ├── libc v0.2.180
│   │   │   │       │   └── shlex v1.3.0
│   │   │   │       ├── pkg-config v0.3.32
│   │   │   │       └── vcpkg v0.2.15
│   │   │   ├── openssl-probe v0.1.6
│   │   │   └── openssl-sys v0.9.111 (*)
│   │   ├── postgres-native-tls v0.5.2
│   │   │   ├── native-tls v0.2.14 (*)
│   │   │   ├── tokio v1.49.0
│   │   │   │   ├── bytes v1.11.1
│   │   │   │   ├── libc v0.2.180
│   │   │   │   ├── mio v1.1.0
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   ├── parking_lot v0.12.5
│   │   │   │   │   ├── lock_api v0.4.14
│   │   │   │   │   │   └── scopeguard v1.2.0
│   │   │   │   │   └── parking_lot_core v0.9.12
│   │   │   │   │       ├── cfg-if v1.0.4
│   │   │   │   │       ├── libc v0.2.180
│   │   │   │   │       └── smallvec v1.15.1
│   │   │   │   ├── pin-project-lite v0.2.16
│   │   │   │   ├── signal-hook-registry v1.4.8
│   │   │   │   │   ├── errno v0.3.14
│   │   │   │   │   │   └── libc v0.2.180
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   ├── socket2 v0.6.1
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   └── tokio-macros v2.6.0 (proc-macro)
│   │   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │       ├── quote v1.0.44 (*)
│   │   │   │       └── syn v2.0.114 (*)
│   │   │   ├── tokio-native-tls v0.3.1
│   │   │   │   ├── native-tls v0.2.14 (*)
│   │   │   │   └── tokio v1.49.0 (*)
│   │   │   └── tokio-postgres v0.7.16
│   │   │       ├── async-trait v0.1.89 (proc-macro) (*)
│   │   │       ├── byteorder v1.5.0
│   │   │       ├── bytes v1.11.1
│   │   │       ├── fallible-iterator v0.2.0
│   │   │       ├── futures-channel v0.3.31
│   │   │       │   ├── futures-core v0.3.31
│   │   │       │   └── futures-sink v0.3.31
│   │   │       ├── futures-util v0.3.31
│   │   │       │   ├── futures-core v0.3.31
│   │   │       │   ├── futures-macro v0.3.31 (proc-macro)
│   │   │       │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │       │   │   ├── quote v1.0.44 (*)
│   │   │       │   │   └── syn v2.0.114 (*)
│   │   │       │   ├── futures-sink v0.3.31
│   │   │       │   ├── futures-task v0.3.31
│   │   │       │   ├── pin-project-lite v0.2.16
│   │   │       │   ├── pin-utils v0.1.0
│   │   │       │   └── slab v0.4.12
│   │   │       ├── log v0.4.29
│   │   │       ├── parking_lot v0.12.5 (*)
│   │   │       ├── percent-encoding v2.3.2
│   │   │       ├── phf v0.13.1
│   │   │       │   └── phf_shared v0.13.1
│   │   │       │       └── siphasher v1.0.2
│   │   │       ├── pin-project-lite v0.2.16
│   │   │       ├── postgres-protocol v0.6.10
│   │   │       │   ├── base64 v0.22.1
│   │   │       │   ├── byteorder v1.5.0
│   │   │       │   ├── bytes v1.11.1
│   │   │       │   ├── fallible-iterator v0.2.0
│   │   │       │   ├── hmac v0.12.1
│   │   │       │   │   └── digest v0.10.7
│   │   │       │   │       ├── block-buffer v0.10.4
│   │   │       │   │       │   └── generic-array v0.14.7
│   │   │       │   │       │       └── typenum v1.19.0
│   │   │       │   │       │       [build-dependencies]
│   │   │       │   │       │       └── version_check v0.9.5
│   │   │       │   │       ├── crypto-common v0.1.7
│   │   │       │   │       │   ├── generic-array v0.14.7 (*)
│   │   │       │   │       │   └── typenum v1.19.0
│   │   │       │   │       └── subtle v2.6.1
│   │   │       │   ├── md-5 v0.10.6
│   │   │       │   │   ├── cfg-if v1.0.4
│   │   │       │   │   └── digest v0.10.7 (*)
│   │   │       │   ├── memchr v2.8.0
│   │   │       │   ├── rand v0.9.2
│   │   │       │   │   ├── rand_chacha v0.9.0
│   │   │       │   │   │   ├── ppv-lite86 v0.2.21
│   │   │       │   │   │   │   └── zerocopy v0.8.39
│   │   │       │   │   │   └── rand_core v0.9.5
│   │   │       │   │   │       └── getrandom v0.3.4
│   │   │       │   │   │           ├── cfg-if v1.0.4
│   │   │       │   │   │           └── libc v0.2.180
│   │   │       │   │   └── rand_core v0.9.5 (*)
│   │   │       │   ├── sha2 v0.10.9
│   │   │       │   │   ├── cfg-if v1.0.4
│   │   │       │   │   ├── cpufeatures v0.2.17
│   │   │       │   │   └── digest v0.10.7 (*)
│   │   │       │   └── stringprep v0.1.5
│   │   │       │       ├── unicode-bidi v0.3.18
│   │   │       │       ├── unicode-normalization v0.1.25
│   │   │       │       │   └── tinyvec v1.10.0
│   │   │       │       │       └── tinyvec_macros v0.1.1
│   │   │       │       └── unicode-properties v0.1.4
│   │   │       ├── postgres-types v0.2.12
│   │   │       │   ├── bytes v1.11.1
│   │   │       │   ├── chrono v0.4.43
│   │   │       │   │   ├── iana-time-zone v0.1.65
│   │   │       │   │   ├── num-traits v0.2.19
│   │   │       │   │   │   [build-dependencies]
│   │   │       │   │   │   └── autocfg v1.5.0
│   │   │       │   │   └── serde v1.0.228 (*)
│   │   │       │   ├── fallible-iterator v0.2.0
│   │   │       │   ├── postgres-protocol v0.6.10 (*)
│   │   │       │   ├── serde_core v1.0.228
│   │   │       │   └── serde_json v1.0.149 (*)
│   │   │       ├── rand v0.9.2 (*)
│   │   │       ├── socket2 v0.6.1 (*)
│   │   │       ├── tokio v1.49.0 (*)
│   │   │       ├── tokio-util v0.7.18
│   │   │       │   ├── bytes v1.11.1
│   │   │       │   ├── futures-core v0.3.31
│   │   │       │   ├── futures-io v0.3.31
│   │   │       │   ├── futures-sink v0.3.31
│   │   │       │   ├── futures-util v0.3.31 (*)
│   │   │       │   ├── hashbrown v0.15.5
│   │   │       │   ├── pin-project-lite v0.2.16
│   │   │       │   ├── slab v0.4.12
│   │   │       │   └── tokio v1.49.0 (*)
│   │   │       └── whoami v2.1.0
│   │   ├── regex v1.12.3
│   │   │   ├── aho-corasick v1.1.4 (*)
│   │   │   ├── memchr v2.8.0
│   │   │   ├── regex-automata v0.4.14 (*)
│   │   │   └── regex-syntax v0.8.9
│   │   ├── serde v1.0.228 (*)
│   │   ├── siphasher v1.0.2
│   │   ├── thiserror v2.0.18
│   │   │   └── thiserror-impl v2.0.18 (proc-macro)
│   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │       ├── quote v1.0.44 (*)
│   │   │       └── syn v2.0.114 (*)
│   │   ├── time v0.3.47 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-postgres v0.7.16 (*)
│   │   ├── toml v0.8.23
│   │   │   ├── serde v1.0.228 (*)
│   │   │   ├── serde_spanned v0.6.9
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   ├── toml_datetime v0.6.11
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   └── toml_edit v0.22.27
│   │   │       ├── indexmap v2.13.0
│   │   │       │   ├── equivalent v1.0.2
│   │   │       │   └── hashbrown v0.16.1
│   │   │       ├── serde v1.0.228 (*)
│   │   │       ├── serde_spanned v0.6.9 (*)
│   │   │       ├── toml_datetime v0.6.11 (*)
│   │   │       ├── toml_write v0.1.2
│   │   │       └── winnow v0.7.14
│   │   ├── url v2.5.8
│   │   │   ├── form_urlencoded v1.2.2
│   │   │   │   └── percent-encoding v2.3.2
│   │   │   ├── idna v1.1.0
│   │   │   │   ├── idna_adapter v1.2.1
│   │   │   │   │   ├── icu_normalizer v2.1.1
│   │   │   │   │   │   ├── icu_collections v2.1.1
│   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro)
│   │   │   │   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │   │   │   │   ├── potential_utf v0.1.4
│   │   │   │   │   │   │   │   └── zerovec v0.11.5
│   │   │   │   │   │   │   │       ├── yoke v0.8.1
│   │   │   │   │   │   │   │       │   ├── stable_deref_trait v1.2.1
│   │   │   │   │   │   │   │       │   ├── yoke-derive v0.8.1 (proc-macro)
│   │   │   │   │   │   │   │       │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │   │   ├── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │   │   └── synstructure v0.13.2
│   │   │   │   │   │   │   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │   │       ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │   │       └── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │   └── zerofrom v0.1.6
│   │   │   │   │   │   │   │       │       └── zerofrom-derive v0.1.6 (proc-macro)
│   │   │   │   │   │   │   │       │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │       │           ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │       │           ├── syn v2.0.114 (*)
│   │   │   │   │   │   │   │       │           └── synstructure v0.13.2 (*)
│   │   │   │   │   │   │   │       ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   │       └── zerovec-derive v0.11.2 (proc-macro)
│   │   │   │   │   │   │   │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   │           ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   │           └── syn v2.0.114 (*)
│   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   ├── icu_normalizer_data v2.1.1
│   │   │   │   │   │   ├── icu_provider v2.1.1
│   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   ├── icu_locale_core v2.1.1
│   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   ├── litemap v0.8.1
│   │   │   │   │   │   │   │   ├── tinystr v0.8.2
│   │   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   │   │   ├── writeable v0.6.2
│   │   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   │   ├── writeable v0.6.2
│   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   ├── zerotrie v0.2.3
│   │   │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │   │   │   │   │   └── zerofrom v0.1.6 (*)
│   │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   │   ├── smallvec v1.15.1
│   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │   │   └── icu_properties v2.1.2
│   │   │   │   │       ├── icu_collections v2.1.1 (*)
│   │   │   │   │       ├── icu_locale_core v2.1.1 (*)
│   │   │   │   │       ├── icu_properties_data v2.1.2
│   │   │   │   │       ├── icu_provider v2.1.1 (*)
│   │   │   │   │       ├── zerotrie v0.2.3 (*)
│   │   │   │   │       └── zerovec v0.11.5 (*)
│   │   │   │   ├── smallvec v1.15.1
│   │   │   │   └── utf8_iter v1.0.4
│   │   │   └── percent-encoding v2.3.2
│   │   └── walkdir v2.5.0
│   │       └── same-file v1.0.6
│   └── refinery-macros v0.9.0 (proc-macro)
│       ├── heck v0.5.0
│       ├── proc-macro2 v1.0.106 (*)
│       ├── quote v1.0.44 (*)
│       ├── refinery-core v0.9.0
│       │   ├── async-trait v0.1.89 (proc-macro) (*)
│       │   ├── cfg-if v1.0.4
│       │   ├── log v0.4.29
│       │   ├── regex v1.12.3 (*)
│       │   ├── siphasher v1.0.2
│       │   ├── thiserror v2.0.18 (*)
│       │   ├── time v0.3.47
│       │   │   ├── deranged v0.5.5
│       │   │   │   └── powerfmt v0.2.0
│       │   │   ├── itoa v1.0.17
│       │   │   ├── num-conv v0.2.0
│       │   │   ├── powerfmt v0.2.0
│       │   │   └── time-core v0.1.8
│       │   ├── url v2.5.8 (*)
│       │   └── walkdir v2.5.0 (*)
│       ├── regex v1.12.3 (*)
│       └── syn v2.0.114 (*)
├── reqwest v0.13.2
│   ├── base64 v0.22.1
│   ├── bytes v1.11.1
│   ├── encoding_rs v0.8.35
│   │   └── cfg-if v1.0.4
│   ├── futures-core v0.3.31
│   ├── h2 v0.4.13
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── fnv v1.0.7
│   │   ├── futures-core v0.3.31
│   │   ├── futures-sink v0.3.31
│   │   ├── http v1.4.0
│   │   │   ├── bytes v1.11.1
│   │   │   └── itoa v1.0.17
│   │   ├── indexmap v2.13.0 (*)
│   │   ├── slab v0.4.12
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   └── tracing v0.1.44 (*)
│   ├── http v1.4.0 (*)
│   ├── http-body v1.0.1
│   │   ├── bytes v1.11.1
│   │   └── http v1.4.0 (*)
│   ├── http-body-util v0.1.3
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   └── pin-project-lite v0.2.16
│   ├── hyper v1.8.1
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── futures-channel v0.3.31 (*)
│   │   ├── futures-core v0.3.31
│   │   ├── h2 v0.4.13 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── httparse v1.10.1
│   │   ├── itoa v1.0.17
│   │   ├── pin-project-lite v0.2.16
│   │   ├── pin-utils v0.1.0
│   │   ├── smallvec v1.15.1
│   │   ├── tokio v1.49.0 (*)
│   │   └── want v0.3.1
│   │       └── try-lock v0.2.5
│   ├── hyper-rustls v0.27.7
│   │   ├── http v1.4.0 (*)
│   │   ├── hyper v1.8.1 (*)
│   │   ├── hyper-util v0.1.20
│   │   │   ├── base64 v0.22.1
│   │   │   ├── bytes v1.11.1
│   │   │   ├── futures-channel v0.3.31 (*)
│   │   │   ├── futures-util v0.3.31 (*)
│   │   │   ├── http v1.4.0 (*)
│   │   │   ├── http-body v1.0.1 (*)
│   │   │   ├── hyper v1.8.1 (*)
│   │   │   ├── ipnet v2.11.0
│   │   │   ├── libc v0.2.180
│   │   │   ├── percent-encoding v2.3.2
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── socket2 v0.6.1 (*)
│   │   │   ├── tokio v1.49.0 (*)
│   │   │   ├── tower-service v0.3.3
│   │   │   └── tracing v0.1.44 (*)
│   │   ├── rustls v0.23.36
│   │   │   ├── aws-lc-rs v1.15.4
│   │   │   │   ├── aws-lc-sys v0.37.1
│   │   │   │   │   [build-dependencies]
│   │   │   │   │   ├── cc v1.2.55 (*)
│   │   │   │   │   ├── cmake v0.1.57
│   │   │   │   │   │   └── cc v1.2.55 (*)
│   │   │   │   │   ├── dunce v1.0.5
│   │   │   │   │   └── fs_extra v1.3.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── once_cell v1.21.3
│   │   │   ├── rustls-pki-types v1.14.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── rustls-webpki v0.103.9
│   │   │   │   ├── aws-lc-rs v1.15.4 (*)
│   │   │   │   ├── rustls-pki-types v1.14.0 (*)
│   │   │   │   └── untrusted v0.9.0
│   │   │   ├── subtle v2.6.1
│   │   │   └── zeroize v1.8.2
│   │   ├── rustls-pki-types v1.14.0 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-rustls v0.26.4
│   │   │   ├── rustls v0.23.36 (*)
│   │   │   └── tokio v1.49.0 (*)
│   │   └── tower-service v0.3.3
│   ├── hyper-util v0.1.20 (*)
│   ├── log v0.4.29
│   ├── mime v0.3.17
│   ├── percent-encoding v2.3.2
│   ├── pin-project-lite v0.2.16
│   ├── rustls v0.23.36 (*)
│   ├── rustls-pki-types v1.14.0 (*)
│   ├── rustls-platform-verifier v0.6.2
│   │   ├── log v0.4.29
│   │   ├── rustls v0.23.36 (*)
│   │   ├── rustls-native-certs v0.8.3
│   │   │   ├── openssl-probe v0.2.1
│   │   │   └── rustls-pki-types v1.14.0 (*)
│   │   └── rustls-webpki v0.103.9 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── serde_urlencoded v0.7.1
│   │   ├── form_urlencoded v1.2.2 (*)
│   │   ├── itoa v1.0.17
│   │   ├── ryu v1.0.23
│   │   └── serde v1.0.228 (*)
│   ├── sync_wrapper v1.0.2
│   │   └── futures-core v0.3.31
│   ├── tokio v1.49.0 (*)
│   ├── tokio-rustls v0.26.4 (*)
│   ├── tower v0.5.3
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── pin-project-lite v0.2.16
│   │   ├── sync_wrapper v1.0.2 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-http v0.6.8
│   │   ├── async-compression v0.4.39
│   │   │   ├── compression-codecs v0.4.36
│   │   │   │   ├── compression-core v0.4.31
│   │   │   │   ├── flate2 v1.1.5
│   │   │   │   │   ├── crc32fast v1.5.0
│   │   │   │   │   │   └── cfg-if v1.0.4
│   │   │   │   │   └── miniz_oxide v0.8.9 (*)
│   │   │   │   └── memchr v2.8.0
│   │   │   ├── compression-core v0.4.31
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   └── tokio v1.49.0 (*)
│   │   ├── bitflags v2.10.0
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── http-body-util v0.1.3 (*)
│   │   ├── iri-string v0.7.10
│   │   ├── pin-project-lite v0.2.16
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   ├── tower v0.5.3 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-service v0.3.3
│   └── url v2.5.8 (*)
├── serde v1.0.228 (*)
├── sql-middleware v0.6.0 (https://github.com/Stinky-c/sql-middleware?rev=950b044967bf652fbd483063b769619b7d1256c3#950b0449)
│   ├── async-trait v0.1.89 (proc-macro) (*)
│   ├── bb8 v0.9.1
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── parking_lot v0.12.5 (*)
│   │   └── tokio v1.49.0 (*)
│   ├── chrono v0.4.43 (*)
│   ├── clap v4.5.57
│   │   ├── clap_builder v4.5.57
│   │   │   ├── anstream v0.6.21
│   │   │   │   ├── anstyle v1.0.13
│   │   │   │   ├── anstyle-parse v0.2.7
│   │   │   │   │   └── utf8parse v0.2.2
│   │   │   │   ├── anstyle-query v1.1.5
│   │   │   │   ├── colorchoice v1.0.4
│   │   │   │   ├── is_terminal_polyfill v1.70.2
│   │   │   │   └── utf8parse v0.2.2
│   │   │   ├── anstyle v1.0.13
│   │   │   ├── clap_lex v0.7.7
│   │   │   └── strsim v0.11.1
│   │   └── clap_derive v4.5.55 (proc-macro)
│   │       ├── heck v0.5.0
│   │       ├── proc-macro2 v1.0.106 (*)
│   │       ├── quote v1.0.44 (*)
│   │       └── syn v2.0.114 (*)
│   ├── crossbeam-channel v0.5.15
│   │   └── crossbeam-utils v0.8.21
│   ├── deadpool v0.12.3
│   │   ├── deadpool-runtime v0.1.4
│   │   ├── lazy_static v1.5.0
│   │   ├── num_cpus v1.17.0
│   │   │   └── libc v0.2.180
│   │   └── tokio v1.49.0 (*)
│   ├── lazy_static v1.5.0
│   ├── parking_lot v0.12.5 (*)
│   ├── regex v1.12.3 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── thiserror v2.0.18 (*)
│   ├── tokio v1.49.0 (*)
│   ├── tokio-postgres v0.7.16 (*)
│   ├── tokio-util v0.7.18 (*)
│   └── tracing v0.1.44 (*)
├── tokio v1.49.0 (*)
├── tokio-util v0.7.18 (*)
├── tracing v0.1.44 (*)
├── tracing-subscriber v0.3.22 (*)
├── uuid v1.21.0
│   ├── getrandom v0.4.1 (*)
│   └── serde_core v1.0.228
└── xxhash-rust v0.8.15

mssql

laundry-data v0.1.0 (/home/runner/work/laundry-data/laundry-data)
├── base64 v0.22.1
├── color-eyre v0.6.5
│   ├── backtrace v0.3.76
│   │   ├── addr2line v0.25.1
│   │   │   └── gimli v0.32.3
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   ├── miniz_oxide v0.8.9
│   │   │   ├── adler2 v2.0.1
│   │   │   └── simd-adler32 v0.3.8
│   │   ├── object v0.37.3
│   │   │   └── memchr v2.8.0
│   │   └── rustc-demangle v0.1.27
│   ├── color-spantrace v0.3.0
│   │   ├── once_cell v1.21.3
│   │   ├── owo-colors v4.2.3
│   │   ├── tracing-core v0.1.36
│   │   │   └── once_cell v1.21.3
│   │   └── tracing-error v0.2.1
│   │       ├── tracing v0.1.44
│   │       │   ├── log v0.4.29
│   │       │   ├── pin-project-lite v0.2.16
│   │       │   ├── tracing-attributes v0.1.31 (proc-macro)
│   │       │   │   ├── proc-macro2 v1.0.106
│   │       │   │   │   └── unicode-ident v1.0.22
│   │       │   │   ├── quote v1.0.44
│   │       │   │   │   └── proc-macro2 v1.0.106 (*)
│   │       │   │   └── syn v2.0.114
│   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │       │   │       ├── quote v1.0.44 (*)
│   │       │   │       └── unicode-ident v1.0.22
│   │       │   └── tracing-core v0.1.36 (*)
│   │       └── tracing-subscriber v0.3.22
│   │           ├── matchers v0.2.0
│   │           │   └── regex-automata v0.4.14
│   │           │       ├── aho-corasick v1.1.4
│   │           │       │   └── memchr v2.8.0
│   │           │       ├── memchr v2.8.0
│   │           │       └── regex-syntax v0.8.9
│   │           ├── nu-ansi-term v0.50.3
│   │           ├── once_cell v1.21.3
│   │           ├── regex-automata v0.4.14 (*)
│   │           ├── serde v1.0.228
│   │           │   ├── serde_core v1.0.228
│   │           │   └── serde_derive v1.0.228 (proc-macro)
│   │           │       ├── proc-macro2 v1.0.106 (*)
│   │           │       ├── quote v1.0.44 (*)
│   │           │       └── syn v2.0.114 (*)
│   │           ├── serde_json v1.0.149
│   │           │   ├── itoa v1.0.17
│   │           │   ├── memchr v2.8.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── zmij v1.0.19
│   │           ├── sharded-slab v0.1.7
│   │           │   └── lazy_static v1.5.0
│   │           ├── smallvec v1.15.1
│   │           ├── thread_local v1.1.9
│   │           │   └── cfg-if v1.0.4
│   │           ├── time v0.3.47
│   │           │   ├── deranged v0.5.5
│   │           │   │   ├── powerfmt v0.2.0
│   │           │   │   └── serde_core v1.0.228
│   │           │   ├── itoa v1.0.17
│   │           │   ├── libc v0.2.180
│   │           │   ├── num-conv v0.2.0
│   │           │   ├── num_threads v0.1.7
│   │           │   ├── powerfmt v0.2.0
│   │           │   ├── serde_core v1.0.228
│   │           │   └── time-core v0.1.8
│   │           ├── tracing v0.1.44 (*)
│   │           ├── tracing-core v0.1.36 (*)
│   │           ├── tracing-log v0.2.0
│   │           │   ├── log v0.4.29
│   │           │   ├── once_cell v1.21.3
│   │           │   └── tracing-core v0.1.36 (*)
│   │           └── tracing-serde v0.2.0
│   │               ├── serde v1.0.228 (*)
│   │               └── tracing-core v0.1.36 (*)
│   ├── eyre v0.6.12
│   │   ├── indenter v0.3.4
│   │   └── once_cell v1.21.3
│   ├── indenter v0.3.4
│   ├── once_cell v1.21.3
│   ├── owo-colors v4.2.3
│   └── tracing-error v0.2.1 (*)
├── config v0.15.19
│   ├── convert_case v0.6.0
│   │   └── unicode-segmentation v1.12.0
│   ├── pathdiff v0.2.3
│   ├── serde_core v1.0.228
│   ├── serde_json v1.0.149 (*)
│   ├── toml v0.9.11+spec-1.1.0
│   │   ├── serde_core v1.0.228
│   │   ├── serde_spanned v1.0.4
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_datetime v0.7.5+spec-1.1.0
│   │   │   └── serde_core v1.0.228
│   │   ├── toml_parser v1.0.6+spec-1.1.0
│   │   │   └── winnow v0.7.14
│   │   └── winnow v0.7.14
│   └── winnow v0.7.14
├── rand v0.10.0
│   ├── chacha20 v0.10.0
│   │   ├── cfg-if v1.0.4
│   │   ├── cpufeatures v0.3.0
│   │   └── rand_core v0.10.0
│   ├── getrandom v0.4.1
│   │   ├── cfg-if v1.0.4
│   │   ├── libc v0.2.180
│   │   └── rand_core v0.10.0
│   └── rand_core v0.10.0
├── refinery v0.9.0
│   ├── refinery-core v0.9.0
│   │   ├── async-trait v0.1.89 (proc-macro)
│   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   ├── quote v1.0.44 (*)
│   │   │   └── syn v2.0.114 (*)
│   │   ├── cfg-if v1.0.4
│   │   ├── futures v0.3.31
│   │   │   ├── futures-channel v0.3.31
│   │   │   │   ├── futures-core v0.3.31
│   │   │   │   └── futures-sink v0.3.31
│   │   │   ├── futures-core v0.3.31
│   │   │   ├── futures-executor v0.3.31
│   │   │   │   ├── futures-core v0.3.31
│   │   │   │   ├── futures-task v0.3.31
│   │   │   │   └── futures-util v0.3.31
│   │   │   │       ├── futures-channel v0.3.31 (*)
│   │   │   │       ├── futures-core v0.3.31
│   │   │   │       ├── futures-io v0.3.31
│   │   │   │       ├── futures-macro v0.3.31 (proc-macro)
│   │   │   │       │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   ├── quote v1.0.44 (*)
│   │   │   │       │   └── syn v2.0.114 (*)
│   │   │   │       ├── futures-sink v0.3.31
│   │   │   │       ├── futures-task v0.3.31
│   │   │   │       ├── memchr v2.8.0
│   │   │   │       ├── pin-project-lite v0.2.16
│   │   │   │       ├── pin-utils v0.1.0
│   │   │   │       └── slab v0.4.12
│   │   │   ├── futures-io v0.3.31
│   │   │   ├── futures-sink v0.3.31
│   │   │   ├── futures-task v0.3.31
│   │   │   └── futures-util v0.3.31 (*)
│   │   ├── log v0.4.29
│   │   ├── regex v1.12.3
│   │   │   ├── aho-corasick v1.1.4 (*)
│   │   │   ├── memchr v2.8.0
│   │   │   ├── regex-automata v0.4.14 (*)
│   │   │   └── regex-syntax v0.8.9
│   │   ├── serde v1.0.228 (*)
│   │   ├── siphasher v1.0.2
│   │   ├── thiserror v2.0.18
│   │   │   └── thiserror-impl v2.0.18 (proc-macro)
│   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │       ├── quote v1.0.44 (*)
│   │   │       └── syn v2.0.114 (*)
│   │   ├── tiberius v0.12.3
│   │   │   ├── async-native-tls v0.4.0
│   │   │   │   ├── futures-util v0.3.31 (*)
│   │   │   │   ├── native-tls v0.2.14
│   │   │   │   │   ├── log v0.4.29
│   │   │   │   │   ├── openssl v0.10.75
│   │   │   │   │   │   ├── bitflags v2.10.0
│   │   │   │   │   │   ├── cfg-if v1.0.4
│   │   │   │   │   │   ├── foreign-types v0.3.2
│   │   │   │   │   │   │   └── foreign-types-shared v0.1.1
│   │   │   │   │   │   ├── libc v0.2.180
│   │   │   │   │   │   ├── once_cell v1.21.3
│   │   │   │   │   │   ├── openssl-macros v0.1.1 (proc-macro)
│   │   │   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │   │   │   └── openssl-sys v0.9.111
│   │   │   │   │   │       └── libc v0.2.180
│   │   │   │   │   │       [build-dependencies]
│   │   │   │   │   │       ├── cc v1.2.55
│   │   │   │   │   │       │   ├── find-msvc-tools v0.1.9
│   │   │   │   │   │       │   ├── jobserver v0.1.34
│   │   │   │   │   │       │   │   └── libc v0.2.180
│   │   │   │   │   │       │   ├── libc v0.2.180
│   │   │   │   │   │       │   └── shlex v1.3.0
│   │   │   │   │   │       ├── pkg-config v0.3.32
│   │   │   │   │   │       └── vcpkg v0.2.15
│   │   │   │   │   ├── openssl-probe v0.1.6
│   │   │   │   │   └── openssl-sys v0.9.111 (*)
│   │   │   │   ├── thiserror v1.0.69
│   │   │   │   │   └── thiserror-impl v1.0.69 (proc-macro)
│   │   │   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │   │       ├── quote v1.0.44 (*)
│   │   │   │   │       └── syn v2.0.114 (*)
│   │   │   │   └── url v2.5.8
│   │   │   │       ├── form_urlencoded v1.2.2
│   │   │   │       │   └── percent-encoding v2.3.2
│   │   │   │       ├── idna v1.1.0
│   │   │   │       │   ├── idna_adapter v1.2.1
│   │   │   │       │   │   ├── icu_normalizer v2.1.1
│   │   │   │       │   │   │   ├── icu_collections v2.1.1
│   │   │   │       │   │   │   │   ├── displaydoc v0.2.5 (proc-macro)
│   │   │   │       │   │   │   │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   │   │   │   │   ├── quote v1.0.44 (*)
│   │   │   │       │   │   │   │   │   └── syn v2.0.114 (*)
│   │   │   │       │   │   │   │   ├── potential_utf v0.1.4
│   │   │   │       │   │   │   │   │   └── zerovec v0.11.5
│   │   │   │       │   │   │   │   │       ├── yoke v0.8.1
│   │   │   │       │   │   │   │   │       │   ├── stable_deref_trait v1.2.1
│   │   │   │       │   │   │   │   │       │   ├── yoke-derive v0.8.1 (proc-macro)
│   │   │   │       │   │   │   │   │       │   │   ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   │   │   │   │       │   │   ├── quote v1.0.44 (*)
│   │   │   │       │   │   │   │   │       │   │   ├── syn v2.0.114 (*)
│   │   │   │       │   │   │   │   │       │   │   └── synstructure v0.13.2
│   │   │   │       │   │   │   │   │       │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   │   │   │   │       │   │       ├── quote v1.0.44 (*)
│   │   │   │       │   │   │   │   │       │   │       └── syn v2.0.114 (*)
│   │   │   │       │   │   │   │   │       │   └── zerofrom v0.1.6
│   │   │   │       │   │   │   │   │       │       └── zerofrom-derive v0.1.6 (proc-macro)
│   │   │   │       │   │   │   │   │       │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   │   │   │   │       │           ├── quote v1.0.44 (*)
│   │   │   │       │   │   │   │   │       │           ├── syn v2.0.114 (*)
│   │   │   │       │   │   │   │   │       │           └── synstructure v0.13.2 (*)
│   │   │   │       │   │   │   │   │       ├── zerofrom v0.1.6 (*)
│   │   │   │       │   │   │   │   │       └── zerovec-derive v0.11.2 (proc-macro)
│   │   │   │       │   │   │   │   │           ├── proc-macro2 v1.0.106 (*)
│   │   │   │       │   │   │   │   │           ├── quote v1.0.44 (*)
│   │   │   │       │   │   │   │   │           └── syn v2.0.114 (*)
│   │   │   │       │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │       │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │       │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │       │   │   │   ├── icu_normalizer_data v2.1.1
│   │   │   │       │   │   │   ├── icu_provider v2.1.1
│   │   │   │       │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │       │   │   │   │   ├── icu_locale_core v2.1.1
│   │   │   │       │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │       │   │   │   │   │   ├── litemap v0.8.1
│   │   │   │       │   │   │   │   │   ├── tinystr v0.8.2
│   │   │   │       │   │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │       │   │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │       │   │   │   │   │   ├── writeable v0.6.2
│   │   │   │       │   │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │       │   │   │   │   ├── writeable v0.6.2
│   │   │   │       │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │       │   │   │   │   ├── zerofrom v0.1.6 (*)
│   │   │   │       │   │   │   │   ├── zerotrie v0.2.3
│   │   │   │       │   │   │   │   │   ├── displaydoc v0.2.5 (proc-macro) (*)
│   │   │   │       │   │   │   │   │   ├── yoke v0.8.1 (*)
│   │   │   │       │   │   │   │   │   └── zerofrom v0.1.6 (*)
│   │   │   │       │   │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │       │   │   │   ├── smallvec v1.15.1
│   │   │   │       │   │   │   └── zerovec v0.11.5 (*)
│   │   │   │       │   │   └── icu_properties v2.1.2
│   │   │   │       │   │       ├── icu_collections v2.1.1 (*)
│   │   │   │       │   │       ├── icu_locale_core v2.1.1 (*)
│   │   │   │       │   │       ├── icu_properties_data v2.1.2
│   │   │   │       │   │       ├── icu_provider v2.1.1 (*)
│   │   │   │       │   │       ├── zerotrie v0.2.3 (*)
│   │   │   │       │   │       └── zerovec v0.11.5 (*)
│   │   │   │       │   ├── smallvec v1.15.1
│   │   │   │       │   └── utf8_iter v1.0.4
│   │   │   │       └── percent-encoding v2.3.2
│   │   │   ├── async-trait v0.1.89 (proc-macro) (*)
│   │   │   ├── asynchronous-codec v0.6.2
│   │   │   │   ├── bytes v1.11.1
│   │   │   │   ├── futures-sink v0.3.31
│   │   │   │   ├── futures-util v0.3.31 (*)
│   │   │   │   ├── memchr v2.8.0
│   │   │   │   └── pin-project-lite v0.2.16
│   │   │   ├── byteorder v1.5.0
│   │   │   ├── bytes v1.11.1
│   │   │   ├── chrono v0.4.43
│   │   │   │   ├── iana-time-zone v0.1.65
│   │   │   │   ├── num-traits v0.2.19
│   │   │   │   │   [build-dependencies]
│   │   │   │   │   └── autocfg v1.5.0
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   ├── connection-string v0.2.0
│   │   │   ├── encoding_rs v0.8.35
│   │   │   │   └── cfg-if v1.0.4
│   │   │   ├── enumflags2 v0.7.12
│   │   │   │   └── enumflags2_derive v0.7.12 (proc-macro)
│   │   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │       ├── quote v1.0.44 (*)
│   │   │   │       └── syn v2.0.114 (*)
│   │   │   ├── futures-util v0.3.31 (*)
│   │   │   ├── num-traits v0.2.19 (*)
│   │   │   ├── once_cell v1.21.3
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── pretty-hex v0.3.0
│   │   │   ├── thiserror v1.0.69 (*)
│   │   │   ├── tokio v1.49.0
│   │   │   │   ├── bytes v1.11.1
│   │   │   │   ├── libc v0.2.180
│   │   │   │   ├── mio v1.1.0
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   ├── parking_lot v0.12.5
│   │   │   │   │   ├── lock_api v0.4.14
│   │   │   │   │   │   └── scopeguard v1.2.0
│   │   │   │   │   └── parking_lot_core v0.9.12
│   │   │   │   │       ├── cfg-if v1.0.4
│   │   │   │   │       ├── libc v0.2.180
│   │   │   │   │       └── smallvec v1.15.1
│   │   │   │   ├── pin-project-lite v0.2.16
│   │   │   │   ├── signal-hook-registry v1.4.8
│   │   │   │   │   ├── errno v0.3.14
│   │   │   │   │   │   └── libc v0.2.180
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   ├── socket2 v0.6.1
│   │   │   │   │   └── libc v0.2.180
│   │   │   │   └── tokio-macros v2.6.0 (proc-macro)
│   │   │   │       ├── proc-macro2 v1.0.106 (*)
│   │   │   │       ├── quote v1.0.44 (*)
│   │   │   │       └── syn v2.0.114 (*)
│   │   │   ├── tokio-util v0.7.18
│   │   │   │   ├── bytes v1.11.1
│   │   │   │   ├── futures-core v0.3.31
│   │   │   │   ├── futures-io v0.3.31
│   │   │   │   ├── futures-sink v0.3.31
│   │   │   │   ├── futures-util v0.3.31 (*)
│   │   │   │   ├── hashbrown v0.15.5
│   │   │   │   ├── pin-project-lite v0.2.16
│   │   │   │   ├── slab v0.4.12
│   │   │   │   └── tokio v1.49.0 (*)
│   │   │   ├── tracing v0.1.44 (*)
│   │   │   └── uuid v1.21.0
│   │   │       ├── getrandom v0.4.1 (*)
│   │   │       └── serde_core v1.0.228
│   │   ├── time v0.3.47 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   ├── toml v0.8.23
│   │   │   ├── serde v1.0.228 (*)
│   │   │   ├── serde_spanned v0.6.9
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   ├── toml_datetime v0.6.11
│   │   │   │   └── serde v1.0.228 (*)
│   │   │   └── toml_edit v0.22.27
│   │   │       ├── indexmap v2.13.0
│   │   │       │   ├── equivalent v1.0.2
│   │   │       │   └── hashbrown v0.16.1
│   │   │       ├── serde v1.0.228 (*)
│   │   │       ├── serde_spanned v0.6.9 (*)
│   │   │       ├── toml_datetime v0.6.11 (*)
│   │   │       ├── toml_write v0.1.2
│   │   │       └── winnow v0.7.14
│   │   ├── url v2.5.8 (*)
│   │   └── walkdir v2.5.0
│   │       └── same-file v1.0.6
│   └── refinery-macros v0.9.0 (proc-macro)
│       ├── heck v0.5.0
│       ├── proc-macro2 v1.0.106 (*)
│       ├── quote v1.0.44 (*)
│       ├── refinery-core v0.9.0
│       │   ├── async-trait v0.1.89 (proc-macro) (*)
│       │   ├── cfg-if v1.0.4
│       │   ├── log v0.4.29
│       │   ├── regex v1.12.3 (*)
│       │   ├── siphasher v1.0.2
│       │   ├── thiserror v2.0.18 (*)
│       │   ├── time v0.3.47
│       │   │   ├── deranged v0.5.5
│       │   │   │   └── powerfmt v0.2.0
│       │   │   ├── itoa v1.0.17
│       │   │   ├── num-conv v0.2.0
│       │   │   ├── powerfmt v0.2.0
│       │   │   └── time-core v0.1.8
│       │   ├── url v2.5.8 (*)
│       │   └── walkdir v2.5.0 (*)
│       ├── regex v1.12.3 (*)
│       └── syn v2.0.114 (*)
├── reqwest v0.13.2
│   ├── base64 v0.22.1
│   ├── bytes v1.11.1
│   ├── encoding_rs v0.8.35 (*)
│   ├── futures-core v0.3.31
│   ├── h2 v0.4.13
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── fnv v1.0.7
│   │   ├── futures-core v0.3.31
│   │   ├── futures-sink v0.3.31
│   │   ├── http v1.4.0
│   │   │   ├── bytes v1.11.1
│   │   │   └── itoa v1.0.17
│   │   ├── indexmap v2.13.0 (*)
│   │   ├── slab v0.4.12
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   └── tracing v0.1.44 (*)
│   ├── http v1.4.0 (*)
│   ├── http-body v1.0.1
│   │   ├── bytes v1.11.1
│   │   └── http v1.4.0 (*)
│   ├── http-body-util v0.1.3
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   └── pin-project-lite v0.2.16
│   ├── hyper v1.8.1
│   │   ├── atomic-waker v1.1.2
│   │   ├── bytes v1.11.1
│   │   ├── futures-channel v0.3.31 (*)
│   │   ├── futures-core v0.3.31
│   │   ├── h2 v0.4.13 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── httparse v1.10.1
│   │   ├── itoa v1.0.17
│   │   ├── pin-project-lite v0.2.16
│   │   ├── pin-utils v0.1.0
│   │   ├── smallvec v1.15.1
│   │   ├── tokio v1.49.0 (*)
│   │   └── want v0.3.1
│   │       └── try-lock v0.2.5
│   ├── hyper-rustls v0.27.7
│   │   ├── http v1.4.0 (*)
│   │   ├── hyper v1.8.1 (*)
│   │   ├── hyper-util v0.1.20
│   │   │   ├── base64 v0.22.1
│   │   │   ├── bytes v1.11.1
│   │   │   ├── futures-channel v0.3.31 (*)
│   │   │   ├── futures-util v0.3.31 (*)
│   │   │   ├── http v1.4.0 (*)
│   │   │   ├── http-body v1.0.1 (*)
│   │   │   ├── hyper v1.8.1 (*)
│   │   │   ├── ipnet v2.11.0
│   │   │   ├── libc v0.2.180
│   │   │   ├── percent-encoding v2.3.2
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   ├── socket2 v0.6.1 (*)
│   │   │   ├── tokio v1.49.0 (*)
│   │   │   ├── tower-service v0.3.3
│   │   │   └── tracing v0.1.44 (*)
│   │   ├── rustls v0.23.36
│   │   │   ├── aws-lc-rs v1.15.4
│   │   │   │   ├── aws-lc-sys v0.37.1
│   │   │   │   │   [build-dependencies]
│   │   │   │   │   ├── cc v1.2.55 (*)
│   │   │   │   │   ├── cmake v0.1.57
│   │   │   │   │   │   └── cc v1.2.55 (*)
│   │   │   │   │   ├── dunce v1.0.5
│   │   │   │   │   └── fs_extra v1.3.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── once_cell v1.21.3
│   │   │   ├── rustls-pki-types v1.14.0
│   │   │   │   └── zeroize v1.8.2
│   │   │   ├── rustls-webpki v0.103.9
│   │   │   │   ├── aws-lc-rs v1.15.4 (*)
│   │   │   │   ├── rustls-pki-types v1.14.0 (*)
│   │   │   │   └── untrusted v0.9.0
│   │   │   ├── subtle v2.6.1
│   │   │   └── zeroize v1.8.2
│   │   ├── rustls-pki-types v1.14.0 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-rustls v0.26.4
│   │   │   ├── rustls v0.23.36 (*)
│   │   │   └── tokio v1.49.0 (*)
│   │   └── tower-service v0.3.3
│   ├── hyper-util v0.1.20 (*)
│   ├── log v0.4.29
│   ├── mime v0.3.17
│   ├── percent-encoding v2.3.2
│   ├── pin-project-lite v0.2.16
│   ├── rustls v0.23.36 (*)
│   ├── rustls-pki-types v1.14.0 (*)
│   ├── rustls-platform-verifier v0.6.2
│   │   ├── log v0.4.29
│   │   ├── rustls v0.23.36 (*)
│   │   ├── rustls-native-certs v0.8.3
│   │   │   ├── openssl-probe v0.2.1
│   │   │   └── rustls-pki-types v1.14.0 (*)
│   │   └── rustls-webpki v0.103.9 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── serde_urlencoded v0.7.1
│   │   ├── form_urlencoded v1.2.2 (*)
│   │   ├── itoa v1.0.17
│   │   ├── ryu v1.0.23
│   │   └── serde v1.0.228 (*)
│   ├── sync_wrapper v1.0.2
│   │   └── futures-core v0.3.31
│   ├── tokio v1.49.0 (*)
│   ├── tokio-rustls v0.26.4 (*)
│   ├── tower v0.5.3
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── pin-project-lite v0.2.16
│   │   ├── sync_wrapper v1.0.2 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-http v0.6.8
│   │   ├── async-compression v0.4.39
│   │   │   ├── compression-codecs v0.4.36
│   │   │   │   ├── compression-core v0.4.31
│   │   │   │   ├── flate2 v1.1.5
│   │   │   │   │   ├── crc32fast v1.5.0
│   │   │   │   │   │   └── cfg-if v1.0.4
│   │   │   │   │   └── miniz_oxide v0.8.9 (*)
│   │   │   │   └── memchr v2.8.0
│   │   │   ├── compression-core v0.4.31
│   │   │   ├── pin-project-lite v0.2.16
│   │   │   └── tokio v1.49.0 (*)
│   │   ├── bitflags v2.10.0
│   │   ├── bytes v1.11.1
│   │   ├── futures-core v0.3.31
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── http v1.4.0 (*)
│   │   ├── http-body v1.0.1 (*)
│   │   ├── http-body-util v0.1.3 (*)
│   │   ├── iri-string v0.7.10
│   │   ├── pin-project-lite v0.2.16
│   │   ├── tokio v1.49.0 (*)
│   │   ├── tokio-util v0.7.18 (*)
│   │   ├── tower v0.5.3 (*)
│   │   ├── tower-layer v0.3.3
│   │   └── tower-service v0.3.3
│   ├── tower-service v0.3.3
│   └── url v2.5.8 (*)
├── serde v1.0.228 (*)
├── sql-middleware v0.6.0 (https://github.com/Stinky-c/sql-middleware?rev=950b044967bf652fbd483063b769619b7d1256c3#950b0449)
│   ├── async-trait v0.1.89 (proc-macro) (*)
│   ├── bb8 v0.9.1
│   │   ├── futures-util v0.3.31 (*)
│   │   ├── parking_lot v0.12.5 (*)
│   │   └── tokio v1.49.0 (*)
│   ├── bb8-tiberius v0.16.0
│   │   ├── bb8 v0.9.1 (*)
│   │   ├── thiserror v1.0.69 (*)
│   │   ├── tiberius v0.12.3 (*)
│   │   ├── tokio v1.49.0 (*)
│   │   └── tokio-util v0.7.18 (*)
│   ├── chrono v0.4.43 (*)
│   ├── clap v4.5.57
│   │   ├── clap_builder v4.5.57
│   │   │   ├── anstream v0.6.21
│   │   │   │   ├── anstyle v1.0.13
│   │   │   │   ├── anstyle-parse v0.2.7
│   │   │   │   │   └── utf8parse v0.2.2
│   │   │   │   ├── anstyle-query v1.1.5
│   │   │   │   ├── colorchoice v1.0.4
│   │   │   │   ├── is_terminal_polyfill v1.70.2
│   │   │   │   └── utf8parse v0.2.2
│   │   │   ├── anstyle v1.0.13
│   │   │   ├── clap_lex v0.7.7
│   │   │   └── strsim v0.11.1
│   │   └── clap_derive v4.5.55 (proc-macro)
│   │       ├── heck v0.5.0
│   │       ├── proc-macro2 v1.0.106 (*)
│   │       ├── quote v1.0.44 (*)
│   │       └── syn v2.0.114 (*)
│   ├── crossbeam-channel v0.5.15
│   │   └── crossbeam-utils v0.8.21
│   ├── deadpool v0.12.3
│   │   ├── deadpool-runtime v0.1.4
│   │   ├── lazy_static v1.5.0
│   │   ├── num_cpus v1.17.0
│   │   │   └── libc v0.2.180
│   │   └── tokio v1.49.0 (*)
│   ├── futures-util v0.3.31 (*)
│   ├── lazy_static v1.5.0
│   ├── parking_lot v0.12.5 (*)
│   ├── regex v1.12.3 (*)
│   ├── serde v1.0.228 (*)
│   ├── serde_json v1.0.149 (*)
│   ├── thiserror v2.0.18 (*)
│   ├── tiberius v0.12.3 (*)
│   ├── tokio v1.49.0 (*)
│   ├── tokio-util v0.7.18 (*)
│   └── tracing v0.1.44 (*)
├── tokio v1.49.0 (*)
├── tokio-util v0.7.18 (*)
├── tracing v0.1.44 (*)
├── tracing-subscriber v0.3.22 (*)
├── uuid v1.21.0 (*)
└── xxhash-rust v0.8.15

Troubleshooting

mssql

If mssql server fails to start or read/write to the data directory, set COMPOSE_UID and COMPOSE_GID to your user and group.

Example mise.{ENV}.local.toml or mise.local.toml. These files are ignored by git.

[env]
COMPOSE_UID = "1000"
COMPOSE_GID = "1000"
2026-02-20 11:01:56 • commit: 740fe46

Schema

Database schema

Rationale

This is a brief description and reason behind all the columns and data types.

LaundryLog

The log table. Uses composite primary key from pep_id and timestamp. Primary tracking table for all machines.

ColumnData TypePurpose
pep_idtextThe pep_id identifiy the machine in a location and position
timestampdatetimeThe time for when this line was entered in
time_remainingintHow many minutes left on the machine
not_available_reasontext nullableThe reason a machine is not available, will be null if available
door_closedboolIf the door is opened or closed
stateMachineStateWhat state the machine is in
settingsjsonThe settings for a current cycle

PhysicalEndpoint

A tracking table that combines location_id, room_id,machine_id, and sticker_number. The pep_id or physical endpoint is derived from 4 other columns. The initial byte slice comes from converting sticker to LE, the machine_id UUID to bytes, converting the room id string (hyphen included) to bytes then the location id UUID to bytes adding them in that order. Using this slice, then hashing using xxhash3 128-bit and base64 encoding it with url safe no padding. This implementation may differ across language which is a bug. See Cargo.toml for package versions. Table includes a added_on datetime column to be able to look up a machine only given 3 components of pep_id.

columnData TypePurpose
added_ondatetime2Maintain when the pep was added to the table
pep_idtextThe base64 encoded pep_id
machine_iduuidA FK to the machines table
location_iduuidA FK to the locations table
room_idtextA FK to the rooms table
sticker_numberintThe machines postional sticker number

Machines

Insight into all machine seen. Depends on API Producers machine_id to be a unique primary key.

ColumnData TypePurpose
machine_iduuidThe PK UUID returned from the API
qr_code_idtextThe qr code short code to the machine
nfc_idtextThe unique id given the nfc tag on the machine
controller_typetextThe controller controling the machine
typeMachineTypeWasher or dryer?
license_platevarchar(7)a license plate on the machine

Rooms

List of all tracked rooms. Depends on API Producer room_id to be a unique primary key.

ColumnData TypePurpose
room_idtextThe primary key from the API
descriptiontext nullableAn optional field describing the location
labeltextThe name of a location

Locations

A location has many Rooms. For helper functions and locale, each room also stores the timezone (timezone) it is in. Create constraint + function/procedure to check if valid timezone. Throw if not valid timezone. See pg_timezone_names or sys.time_zone_info. Has a label, description, and machine sum.

ColumnData TypePurpose
location_iduuidThe PK uuid from the API
descriptiontext nullableAn optional description
labeltextThe name of the location
timezonetextA convience field for converting times
2026-03-02 13:52:56 • commit: dd00d1f

Wishes

Extra features I want. However, this project is for a grade.

Tests

Likely to use a mock api serving JSON files. Design to be API compatible with CSC so testing is a simple endpoint swap. E2E style tests, data is put into the database and a test grabs to check

Backfilling

This is a timescale feature. It helps fill in continuous data even if the source is not responding. This solves the problem of when the CSC API stops responding to requests.

Updating backfilled data

If backfilling is implemented, ensure that backfilled data is properly updated after service resumes. For example, if a machine is started in the time frame where service is out then return to old data and update the row where a machine changes state.

Load Claiming

A person can claim a load of laundry, which creates a laundry load for both washer and dryer connecting it to a log table.

Adds tables

  • User
  • LaundryLoad
  • WasherLaundryLoads
  • DryerLaundryLoad
  • UserLogClaim

Error Notifications

See ApiLog. A handler for the API Log to connect to a notification provider to send.

2026-03-01 10:00:46 • commit: 1f32f88

Considerations

  • Use stream API for real time updates
  • Support MsSQl for final grade
  • Single timestamp for entire insert into ApiLog and LaundryLog
  • machines may have a collision. If a machine is replaced in a room, both the room_id and sticker_number will be the same.
    • Solve using last_seen timestamp and add constraint to block collisions.
  • Create views for rooms and locations dynamically.

Machine state transitions

A machine follows usually follows a cycle of state changes. The cycle looks like pressStart => running => idle => pressStart. An important note, when the machine completes and moves to the idle state, opening the door moves it to the pressStart state even if it was never emptied. This means someone can leave their laundry inside the machine after opening the door and it will be seen as free. Fixing this problem is out of the project’s scope.

2026-02-06 10:26:48 • commit: b3fc7f7

Sql Server Extras

May be able to be used for other dialects but designed for SQL Server.

SELECT *
from Locations;

SELECT *
from Rooms;

SELECT *
FROM Machines

SELECT *
FROM PhysicalEndpoint

-- List the name of room + location for every machine
SELECT sticker_number, Rooms.label, Locations.label
FROM Machines
         JOIN PhysicalEndpoint ON Machines.machine_id = PhysicalEndpoint.machine_id
         JOIN Rooms ON PhysicalEndpoint.room_id = Rooms.room_id
         JOIN Locations ON PhysicalEndpoint.location_id = Locations.location_id


--- Return all the latest log entries
CREATE FUNCTION func_LatestLogs()
    RETURNS TABLE
        AS RETURN(SELECT MAX([timestamp]) as [timestamp], pep_id
                  FROM LaundryLog
                  GROUP BY pep_id);

-- Join the latest entries back to the table
CREATE FUNCTION func_LatestLogsWithFields()
    RETURNS TABLE
        AS RETURN(SELECT LaundryLog.*
                  FROM dbo.LatestLogs() T
                           JOIN LaundryLog ON LaundryLog.timestamp = T.timestamp AND
                                              LaundryLog.pep_id = T.pep_id)


CREATE PROCEDURE sp_CurrentState(@pep_id NVARCHAR(255))
AS
BEGIN
    SELECT *
    FROM dbo.LatestLogsWithFields()
    WHERE pep_id = @pep_id
END;
GO

EXEC sp_currentState @pep_id = 'yZWM2OzN1dmasHzWWH2X2A';

-- Return all columns for a machine, room, and location given a pep
CREATE PROCEDURE sp_reversePep(@pep_id NVARCHAR(255))
AS
BEGIN
    SELECT *
    FROM PhysicalEndpoint
             JOIN Rooms ON Rooms.room_id = PhysicalEndpoint.room_id
             JOIN Machines ON Machines.machine_id = PhysicalEndpoint.machine_id
             JOIN Locations ON PhysicalEndpoint.location_id = Locations.location_id
    WHERE pep_id = @pep_id

END;
GO

EXEC sp_reversePep @pep_id = 'yZWM2OzN1dmasHzWWH2X2A';


-- Count number of machines in each room
SELECT COUNT(DISTINCT machines.machine_id) AS [count], PhysicalEndpoint.room_id
FROM Machines
         JOIN PhysicalEndpoint on Machines.machine_id = PhysicalEndpoint.machine_id
GROUP BY PhysicalEndpoint.room_id

-- Count Number of machines in every location
SELECT COUNT(DISTINCT machines.machine_id) AS [count], PhysicalEndpoint.location_id
FROM Machines
         JOIN PhysicalEndpoint on Machines.machine_id = PhysicalEndpoint.machine_id
GROUP BY PhysicalEndpoint.location_id

-- Function for counting every machine
CREATE FUNCTION func_CountEveryMachine() RETURNS INT
AS
BEGIN
    DECLARE @machineCount INT;
    SELECT @machineCount
               = COUNT(DISTINCT machine_id)
    FROM MACHINES
    RETURN @machineCount
END

-- Trigger version of machine counting
CREATE TABLE RoomMachineCount
(
    room_id nvarchar(255) unique,
    count   INT
);

-- Create a trigger that recalculates machine count for every room that had a machine insert
CREATE TRIGGER trigger_machineCount
    ON Machines
    AFTER INSERT , UPDATE
    AS
BEGIN
    -- Create a table of all affected rooms
    DECLARE @rooms TABLE
                   (
                       room_id NVARCHAR(255)
                   );
    INSERT INTO @rooms
    SELECT PhysicalEndpoint.room_id
    FROM inserted
             JOIN PhysicalEndpoint
                  ON inserted.machine_id = PhysicalEndpoint.machine_id

    -- Clean old data
    DELETE RoomMachineCount WHERE room_id in (@rooms)

    -- Update all affected rooms with new machine count
    INSERT INTO RoomMachineCount
    SELECT COUNT(DISTINCT machines.machine_id) AS [count], room_id
    FROM Machines
             JOIN PhysicalEndpoint ON PhysicalEndpoint.machine_id = Machines.machine_id
    WHERE PhysicalEndpoint.room_id IN (@rooms)
    GROUP BY PhysicalEndpoint.room_id

END
GO

DROP TABLE RoomMachineCount
DROP TRIGGER trigger_machineCount

-- Fast row counting
-- This table will grow fast so a less compute intensive method is needed
-- 45 machines * 1440 minutes (60 minutes * 24 hours * 1 day) =
-- = ~64800 per day
SELECT (dbo.func_CountEveryMachine() * (60 * 24)) AS 'RowsPerDay'

-- https://www.brentozar.com/archive/2014/02/count-number-rows-table-sql-server/
CREATE PROCEDURE sp_countRows(@object_id sysname) AS
BEGIN
    SELECT TBL.object_id, TBL.name, SUM(PART.rows) AS rows
    FROM sys.tables TBL
             INNER JOIN sys.partitions PART ON TBL.object_id = PART.object_id
             INNER JOIN sys.indexes IDX ON PART.object_id = IDX.object_id
        AND PART.index_id = IDX.index_id
    WHERE TBL.name = @object_id
      AND IDX.index_id < 2
    GROUP BY TBL.object_id, TBL.name;
END;

    EXEC sp_countRows @object_id = 'LaundryLog'
2026-03-15 13:42:55 • commit: bd27727