candding 0.1.0

Pure candle embeddings for Rust with no ONNX: dense, sparse, multi-vector and rerank models today, image models on the roadmap
Documentation
//! One fetch of a repository at a time, across threads and processes: an exclusive lock on a file in candding's own
//! directory of the cache root, held until the fetch returns.

use std::fs;
use std::fs::File;
use std::fs::TryLockError;
use std::io;
use std::path::Path;

use crate::hub::cache;

/// Locks `repo_id` in the cache at `root`, waiting while another fetch holds it; dropping the file releases it.
pub(super) fn repository(root: &Path, repo_id: &str) -> io::Result<File> {
  let name = format!("{}.lock", cache::repo_dir_name(repo_id));
  let path = root.join(".candding").join("locks").join(name);
  if let Some(parent) = path.parent() {
    fs::create_dir_all(parent)?;
  }
  let file = File::options()
    .create(true)
    .truncate(false)
    .write(true)
    .open(&path)?;
  match file.try_lock() {
    Ok(()) => {}
    Err(TryLockError::WouldBlock) => {
      tracing::info!(repo_id, "waiting for another fetch of the same model");
      file.lock()?;
    }
    Err(TryLockError::Error(error)) => return Err(error),
  }
  Ok(file)
}