pub struct Pauses {
pub conn: Arc<Mutex<Connection>>,
pub min_duration: Option<String>,
pub max_duration: Option<String>,
}Expand description
Database manager for pause/break tracking operations.
The Pauses struct provides a high-level interface for managing work break
records in the database. It uses thread-safe connection handling to support
concurrent access from the activity monitor and user commands.
§Thread Safety
The connection is wrapped in an Arc<Mutex<>> to allow safe concurrent access
from multiple threads, particularly important when the activity monitor
is running in the background while users interact with the CLI.
§Connection Management
Each Pauses instance maintains its own database connection and ensures
the pauses table schema is properly initialized on creation.
Fields§
§conn: Arc<Mutex<Connection>>Thread-safe database connection wrapper.
The connection is protected by a mutex to prevent race conditions when multiple threads attempt to record or query pause data simultaneously.
min_duration: Option<String>§max_duration: Option<String>Implementations§
Source§impl Pauses
impl Pauses
Sourcepub fn new() -> Result<Pauses>
pub fn new() -> Result<Pauses>
Creates a new Pauses instance and initializes the database schema.
This constructor establishes a database connection, ensures the pauses table exists with the proper schema, and wraps the connection for thread-safe access. The schema creation is idempotent and safe to call multiple times.
§Returns
Returns a new Pauses instance ready for pause tracking operations,
or an error if database initialization fails.
§Example
use kasl::db::pauses::Pauses;
let pauses = Pauses::new()?;
// Ready to track pauses§Errors
Returns an error if:
- Database connection cannot be established
- Schema creation fails due to permissions or corruption
- Table initialization encounters SQL errors
pub fn set_min_duration(&self, min_duration: u64) -> Self
pub fn set_max_duration(&self, max_duration: u64) -> Self
Sourcepub fn insert_start(&self) -> Result<()>
pub fn insert_start(&self) -> Result<()>
Records the start of a new pause with the current timestamp.
This method creates a new pause record using the current system time
as the start timestamp. The pause remains “open” (end IS NULL) until
it’s completed with insert_end(). Multiple open pauses are allowed
to handle edge cases in activity detection.
§Returns
Returns Ok(()) if the pause start is recorded successfully,
or an error if the database operation fails.
§Example
let pauses = Pauses::new()?;
pauses.insert_start()?; // Pause started at current time§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads, such as the activity monitor daemon.
Sourcepub fn insert_start_with_time(&self, start_time: NaiveDateTime) -> Result<()>
pub fn insert_start_with_time(&self, start_time: NaiveDateTime) -> Result<()>
Records the start of a new pause with a specific timestamp.
This method allows manual insertion of pause records with exact timestamps, useful for importing historical data or correcting activity tracking records. The specified time should be in the local timezone for consistency with other records.
§Arguments
start_time- The exact timestamp when the pause began
§Returns
Returns Ok(()) if the pause is recorded successfully,
or an error if the database operation fails.
§Example
use chrono::NaiveDateTime;
let pauses = Pauses::new()?;
let start_time = NaiveDateTime::parse_from_str(
"2025-01-15 14:30:00",
"%Y-%m-%d %H:%M:%S"
)?;
pauses.insert_start_with_time(start_time)?;§Data Integrity
The caller is responsible for ensuring the timestamp is reasonable and doesn’t conflict with existing work session boundaries.
Sourcepub fn insert_end(&self) -> Result<()>
pub fn insert_end(&self) -> Result<()>
Completes the most recent open pause with duration calculation.
This method finds the last pause record that has a start time but no end time, then updates it with the current timestamp and the provided duration. The duration is typically calculated by the activity monitor based on the actual inactive period.
§Duration Calculation
While the end timestamp is set to the current time, the duration parameter contains the actual pause length in seconds. This allows for accurate tracking even when there’s a delay between activity resumption and pause recording.
§Returns
Returns Ok(()) if the pause is completed successfully, or an error
if no open pause exists or the database operation fails.
§Example
let pauses = Pauses::new()?;
pauses.insert_start()?;
// ... user is inactive for 5 minutes ...
pauses.insert_end()?;§Behavior Notes
- Only affects the most recent open pause record
- If no open pause exists, the operation may fail silently
- Duration should be a positive number of seconds
Sourcepub fn insert_manual(
&self,
start: NaiveDateTime,
duration: TimeDelta,
protected: bool,
reason: Option<&str>,
) -> Result<i64>
pub fn insert_manual( &self, start: NaiveDateTime, duration: TimeDelta, protected: bool, reason: Option<&str>, ) -> Result<i64>
Records a complete pause stated by the user, with explicit bounds.
Unlike monitor-detected pauses, which are opened by insert_start and
closed later by insert_end, a manual pause is written in one shot: the
user knows when they left and how long they were gone. No placement is
inferred and no time is invented.
§Arguments
start- When the absence beganduration- How long it lastedprotected- Exempt the record from threshold filtering and mergingreason- Optional note describing the absence
§Returns
Returns the id of the inserted pause record.
Sourcepub fn find_overlapping(
&self,
start: NaiveDateTime,
end: NaiveDateTime,
) -> Result<Option<Pause>>
pub fn find_overlapping( &self, start: NaiveDateTime, end: NaiveDateTime, ) -> Result<Option<Pause>>
Returns the pause overlapping the given time range, if any exists.
Used to reject a manual pause that would collide with an already recorded one, so the day never contains contradictory absences.
Sourcepub fn get_daily_pauses(&self, date: NaiveDate) -> Result<Vec<Pause>>
pub fn get_daily_pauses(&self, date: NaiveDate) -> Result<Vec<Pause>>
Retrieves all pause records for a specific date with duration filtering.
This method fetches all completed pause records for the given date that meet or exceed the specified minimum duration threshold. It’s commonly used for daily reporting and work time calculations where very short pauses (e.g., under 5 minutes) may be ignored.
§Filtering Logic
- Only includes pauses that started on the specified date
- Filters out pauses shorter than the minimum duration
- Includes ongoing pauses (duration IS NULL) regardless of threshold
- Results are ordered by start time for chronological display
§Arguments
date- The target date to query (uses local timezone)min_duration- Minimum pause length to include (in minutes)
§Returns
Returns a vector of Pause objects representing the filtered pause
records, or an error if the database query fails.
§Example
use chrono::Local;
// Get pauses of 10 minutes or longer
let pauses = Pauses::new()?.set_min_duration(10);
let today = Local::now().date_naive();
let significant_pauses = pauses.get_daily_pauses(today)?;
for pause in significant_pauses {
println!("Pause: {:?} - {:?}", pause.start, pause.end);
}§Performance Notes
This query uses date functions and may be slower on large datasets. Consider adding indices on the start column for better performance.
Sourcepub fn get_workday_pauses(&self, workday: &Workday) -> Result<Vec<Pause>>
pub fn get_workday_pauses(&self, workday: &Workday) -> Result<Vec<Pause>>
Fetches daily pauses and keeps only the portions inside the workday bounds.
Drops pauses entirely before workday.start or after workday.end, and
clips straddling pauses to [workday.start, workday.end].
Sourcepub fn delete(&self, id: i32) -> Result<()>
pub fn delete(&self, id: i32) -> Result<()>
Deletes a single pause record by its unique identifier.
This method removes a specific pause record from the database, typically used for correcting erroneous pause recordings or user-requested deletions. The operation is permanent and cannot be undone without database backups.
§Arguments
id- The unique identifier of the pause record to delete
§Returns
Returns Ok(()) if the deletion succeeds, or an error if the
database operation fails. Note that deleting a non-existent
record is not considered an error.
§Example
let pauses = Pauses::new()?;
pauses.delete(123)?; // Delete pause with ID 123§Safety Considerations
- Deletion is immediate and permanent
- No confirmation prompts are provided at this level
- Callers should implement appropriate confirmation flows
Sourcepub fn delete_many(&self, ids: &[i32]) -> Result<usize>
pub fn delete_many(&self, ids: &[i32]) -> Result<usize>
Deletes multiple pause records efficiently in a batch operation.
This method removes multiple pause records in a single transaction, providing better performance than individual deletions and ensuring atomicity. If any deletion fails, all changes are rolled back.
§Transaction Handling
All deletions are performed within a single database transaction to ensure consistency. Either all specified records are deleted or none are deleted if any error occurs.
§Arguments
ids- Slice of pause record IDs to delete
§Returns
Returns the number of records actually deleted, or an error if the batch operation fails. The count may be less than the input length if some IDs don’t exist in the database.
§Example
let pauses = Pauses::new()?;
let ids_to_delete = vec![101, 102, 103];
let deleted_count = pauses.delete_many(&ids_to_delete)?;
println!("Deleted {} pause records", deleted_count);§Performance Benefits
- Single transaction reduces database overhead
- More efficient than individual delete operations
- Atomic operation ensures data consistency
§Edge Cases
- Empty input slice returns 0 without database interaction
- Non-existent IDs are silently ignored
- Partial failures result in complete rollback