Skip to content

Commit

Permalink
Refactor tests and update ingestion handling logic
Browse files Browse the repository at this point in the history
Removed outdated test files for configuration and database as they no longer align with the current testing strategy. Enhanced `UpdateIngestion` struct by refining the handling of optional fields and integrated asynchronous database updates using `smol::block_on`. This improves code clarity and prepares for more efficient and scalable ingestion operations.
  • Loading branch information
keinsell committed Dec 9, 2024
1 parent 69086d5 commit 34d7f00
Show file tree
Hide file tree
Showing 13 changed files with 650 additions and 281 deletions.
631 changes: 470 additions & 161 deletions cli/Cargo.lock

Large diffs are not rendered by default.

18 changes: 12 additions & 6 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@ name = "neuronek-cli"
description = "🧬 Intelligent dosage tracker application with purpose to monitor supplements, nootropics and psychoactive substances along with their long-term influence on one's mind and body."
version = "0.0.0-dev.1"
edition = "2024"
path = "src/main.rs"

[dependencies]
smol = "2.0.2"
chrono-english = "0.1.7"
tracing = "0.1.40"
tracing-attributes = "0.1.27"
openssl = { version = "0.10", features = ["vendored"] }
#openssl = { version = "0.10", features = ["vendored"] }
serde = "1.0.213"
config = "0.14.1"
serde_json = "1.0.132"
directories = "5.0.1"
async-trait = "0.1.83"
sea-orm-migration = { version = "1.1.0", features = [
"runtime-async-std-native-tls",
"runtime-async-std-rustls",
"sqlx-sqlite",
"with-chrono",
"sea-orm-cli",
"with-bigdecimal",
"sea-orm-cli"
] }
sea-orm = { version = "1.1.0", features = [
"runtime-async-std-native-tls",
"runtime-async-std-rustls",
"sqlx-sqlite",
"with-chrono",
"with-bigdecimal"
] }
chrono = "0.4.38"
lazy_static = "1.5.0"
Expand All @@ -39,10 +40,15 @@ tracing-appender = "0.2"
time = { version = "0.3", features = ["formatting"] }
anyhow = "1.0.93"
temp-dir = "0.1.14"
cli-table = "0.4.9"
tabled = "0.17.0"
smol-macros = "0.1.1"
cargo-expand = { version = "1.0.95", optional = true }

[dev-dependencies]
pretty_assertions = "1.4.1"
tempfile = "3.13.0"
assert_cmd = "2.0.11"

[features]
cargo-expand = ["dep:cargo-expand"]

91 changes: 38 additions & 53 deletions cli/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,32 @@ VERSION --global-cache 0.8
PROJECT keinsell/neuronek-cli
IMPORT github.com/earthly/lib/rust:3.0.1 AS rust

install:
FROM rustlang/rust:nightly
DO rust+INIT --keep_fingerprints=true
DO rust+SET_CACHE_MOUNTS_ENV
DO rust+CARGO --args="install cargo-binstall"
DO rust+CARGO --args="binstall -y cargo-tarpaulin cargo-llvm-cov"

checkout:
FROM +install
WORKDIR /tmp
COPY --keep-ts Cargo.lock Cargo.toml ./
CHECKOUT:
FUNCTION
WORKDIR /tmp/neuronek-cli
COPY --keep-ts Cargo.toml ./
COPY --keep-ts --dir src ./
COPY --keep-ts --dir tests ./

lint:
FROM +checkout
RUN rustup component add clippy
DO rust+CARGO --args="clippy --all-features --all-targets --offline -- -D warnings"
builder:
# ARG IMAGE=registry.suse.com/bci/rust:1.82
ARG IMAGE=ghcr.io/rust-cross/cargo-zigbuild:latest
FROM $IMAGE
RUN rustup default nightly
DO rust+INIT --keep_fingerprints=true
DO +CHECKOUT

fmt:
FROM +lint
RUN rustup component add rustfmt
FROM +builder
RUN rustup component add fmt
DO rust+CARGO --args="fmt --check"

build:
FROM +checkout
DO rust+CARGO --args="build --release" --output="release/[^/\.]+"
SAVE ARTIFACT ./target/release/neuronek-cli neuronek-cli AS LOCAL dist/neuronek-cli
lint:
FROM +fmt
RUN rustup component add clippy
DO rust+CARGO --args="clippy --all-features --all-targets -- -D warnings"

test:
FROM +build
FROM +lint
DO rust+CARGO --args="test"

coverage:
Expand All @@ -44,35 +39,25 @@ coverage:
SAVE ARTIFACT ./lcov.info AS LOCAL lcov.info
SAVE ARTIFACT ./coverage AS LOCAL coverage

all:
BUILD +lint
BUILD +fmt
BUILD +build
BUILD +test


crossbuild:
ARG RUST_TARGET
ARG BASE_IMAGE=ghcr.io/rust-cross/cargo-zigbuild:latest
FROM +builder --IMAGE=$BASE_IMAGE
RUN rustup target add $RUST_TARGET
RUN cargo zigbuild --release --target $RUST_TARGET
SAVE ARTIFACT ./target/$RUST_TARGET/release AS LOCAL ./target/$RUST_TARGET/release
SAVE ARTIFACT ./target/$RUST_TARGET/release $RUST_TARGET

# Package Self-Extracting Archive
# ===============================
# Archive which will contain application
# binary, license, documentation and all
# other files necessary for distribution.
# Such archive have ability to unpack itself
# into targeted directory (usually $PATH).
package-xar:
FROM registry.suse.com/bci/kiwi:9.24

package-flatpak:
FROM registry.suse.com/bci/kiwi:9.24

package-nix:
FROM registry.suse.com/bci/kiwi:9.24
build:
BUILD +crossbuild \
--RUST_TARGET=x86_64-pc-windows-gnu \
--RUST_TARGET=x86_64-unknown-linux-gnu \
--RUST_TARGET=aarch64-unknown-linux-gnu \
--RUST_TARGET=x86_64-apple-darwin \
--RUST_TARGET=aarch64-apple-darwin

# Container
# =========
# ...
package-container:
FROM registry.suse.com/bci/bci-micro:15.5
COPY +build/target/release/neuronek neuronek
ENTRYPOINT ["./neuronek"]
SAVE IMAGE --push neuronek/cli:dev
all:
BUILD +fmt
BUILD +lint
BUILD +test
BUILD +build
1 change: 0 additions & 1 deletion cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ impl AppConfig
pub fn new() -> Result<Self, ConfigError>
{
let mut builder = ConfigBuilder::builder()
// Start off with default values
.set_default("database_url", default_database_url())?
.set_default("debug", false)?
.set_default("log_level", default_log_level())?;
Expand Down
5 changes: 3 additions & 2 deletions cli/src/ingestion/delete_ingestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ use smol::block_on;
#[command(version, about = "Update ingestion", long_about)]
pub struct DeleteIngestion
{
/// Identificator of the ingestion to be deleted
/// Identification of the ingestion to be deleted
#[arg(short = 'i', long = "id")]
pub ingestion_id: i32,
}

#[async_trait::async_trait]
impl CommandHandler for DeleteIngestion
{
fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
async fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
{
let rows_affected = block_on(async {
Ingestion::delete_by_id(self.ingestion_id)
Expand Down
13 changes: 8 additions & 5 deletions cli/src/ingestion/list_ingestions.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use tracing::Level;
use crate::database;
use crate::database::prelude::Ingestion;
use crate::ingestion::ViewModel;
use crate::lib::CommandHandler;
use async_trait::async_trait;
use clap::Parser;
use sea_orm::{DatabaseConnection, QuerySelect};
use sea_orm::DatabaseConnection;
use sea_orm::EntityTrait;
use sea_orm::QueryOrder;
use sea_orm::QuerySelect;
use smol::block_on;
use tabled::Table;
use tracing_attributes::instrument;
Expand All @@ -22,10 +23,12 @@ pub struct ListIngestions
// TODO: Return format (JSON/Pretty)
}


#[async_trait]
impl CommandHandler for ListIngestions
{
#[instrument(name = "list_ingestions", level = Level::INFO)]
fn handle(&self, database_connection: &DatabaseConnection) -> anyhow::Result<(), String>
#[instrument(level = Level::INFO, skip(database_connection), nane = "ListIngestions")]
async fn handle(&self, database_connection: &DatabaseConnection) -> anyhow::Result<(), String>
{
let ingestions = block_on(async {
Ingestion::find()
Expand All @@ -50,4 +53,4 @@ impl CommandHandler for ListIngestions

Ok(())
}
}
}
4 changes: 3 additions & 1 deletion cli/src/ingestion/log_ingestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::lib::CommandHandler;
use crate::route_of_administration::RouteOfAdministrationClassification;
use anyhow::Context;
use anyhow::Result;
use async_trait::async_trait;
use chrono::DateTime;
use chrono::Local;
use chrono_english::Dialect;
Expand Down Expand Up @@ -72,10 +73,11 @@ pub enum LogIngestionError
DatabaseError(#[from] sea_orm::DbErr),
}

#[async_trait]
impl CommandHandler for LogIngestion
{
#[instrument(name = "log_ingestion", level = Level::INFO)]
fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
async fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
{
let ingestion = block_on(async {
database::ingestion::Entity::insert(database::ingestion::ActiveModel {
Expand Down
42 changes: 37 additions & 5 deletions cli/src/ingestion/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use crate::database::ingestion;
use async_trait::async_trait;
use chrono::DateTime;
use chrono::Utc;
use clap::Args;
use clap::Parser;
use clap::Subcommand;
use clap::command;
use sea_orm::DatabaseConnection;
use serde::Deserialize;
use serde::Serialize;
use tabled::Tabled;
Expand All @@ -11,6 +17,7 @@ mod list_ingestions;
mod log_ingestion;
mod update_ingestion;

use crate::lib::CommandHandler;
pub use delete_ingestion::DeleteIngestion;
pub use list_ingestions::ListIngestions;
pub use log_ingestion::LogIngestion;
Expand All @@ -34,11 +41,36 @@ pub enum IngestionError
NotFound(#[from] sea_orm::DbErr),
}

pub enum IngestionCommands {
LogIngestion(LogIngestion),
UpdateIngestion(UpdateIngestion),
DeleteIngestion(DeleteIngestion),
ListIngestions(ListIngestions),
#[derive(Debug, Subcommand)]
pub enum IngestionCommands
{
Log(LogIngestion),
Update(UpdateIngestion),
Delete(DeleteIngestion),
List(ListIngestions),
}

#[derive(Debug, Args)]
#[command(name = "ingestion")]
pub struct IngestionRouter
{
#[command(subcommand)]
commands: IngestionCommands,
}

#[async_trait]
impl CommandHandler for IngestionRouter
{
async fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
{
match &self.commands
{
| IngestionCommands::Log(command) => command.handle(database_connection).await,
| IngestionCommands::Update(command) => command.handle(database_connection).await,
| IngestionCommands::Delete(command) => command.handle(database_connection).await,
| IngestionCommands::List(command) => command.handle(database_connection).await,
}
}
}

impl std::fmt::Display for ViewModel
Expand Down
3 changes: 2 additions & 1 deletion cli/src/ingestion/update_ingestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ pub struct UpdateIngestion
pub route_of_administration: Option<RouteOfAdministrationClassification>,
}

#[async_trait::async_trait]
impl CommandHandler for UpdateIngestion
{
fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
async fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>
{
let mut ingestion = block_on(async {
Ingestion::find_by_id(self.ingestion_id)
Expand Down
6 changes: 4 additions & 2 deletions cli/src/lib/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod dosage;

use async_trait::async_trait;
use sea_orm::DatabaseConnection;

pub trait CommandHandler
#[async_trait]
pub trait CommandHandler: Sync
{
fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>;
async fn handle(&self, database_connection: &DatabaseConnection) -> Result<(), String>;
}
31 changes: 22 additions & 9 deletions cli/src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
use anyhow::Context;
use anyhow::Result;
use directories::ProjectDirs;
use std::fs::OpenOptions;
use tracing::{Level, Subscriber};
use tracing_subscriber::{prelude::*, Registry};
use tracing::Level;
use tracing::Subscriber;
use tracing_subscriber::Registry;
use tracing_subscriber::fmt::format::FmtSpan;
use anyhow::{Context, Result};
use directories::ProjectDirs;
use tracing_subscriber::prelude::*;

pub fn setup_logging() -> Result<(), Box<dyn std::error::Error>> {
pub fn setup_logging() -> Result<(), Box<dyn std::error::Error>>
{
let file = OpenOptions::new()
.create(true)
.append(true)
.open(ProjectDirs::from("com", "neuronek", "cli", ).expect("Failed to get project directories").cache_dir().join("neuronek.log"))
.open(
ProjectDirs::from("com", "neuronek", "cli")
.expect("Failed to get project directories")
.cache_dir()
.join("neuronek.log"),
)
.context("Failed to open log file")?;

let file_writer = file.with_max_level(Level::ERROR);
Expand Down Expand Up @@ -41,12 +50,16 @@ pub fn setup_logging() -> Result<(), Box<dyn std::error::Error>> {
}

#[cfg(test)]
mod tests {
use tracing::{error, info, warn};
mod tests
{
use super::*;
use tracing::error;
use tracing::info;
use tracing::warn;

#[test]
fn test_logging() {
fn test_logging()
{
setup_logging().unwrap();
info!("Test log message");
warn!("Test warning message");
Expand Down
Loading

0 comments on commit 34d7f00

Please sign in to comment.