chore: add tabby-scheduler [TAB-17] (#192)
* add scheduler * update fmt * add integration tests for schedulerdocs-add-demo
parent
63ca6225ba
commit
da02d471a9
|
|
@ -708,6 +708,15 @@ dependencies = [
|
||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filenamify"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b781e8974b2cc71ac3c587c881c11ee5fe9a379f43503674e1e1052647593b4c"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
|
@ -2163,6 +2172,15 @@ dependencies = [
|
||||||
"serdeconv",
|
"serdeconv",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tabby-scheduler"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"filenamify",
|
||||||
|
"tabby-common",
|
||||||
|
"temp_testdir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tar"
|
name = "tar"
|
||||||
version = "0.4.38"
|
version = "0.4.38"
|
||||||
|
|
@ -2174,6 +2192,12 @@ dependencies = [
|
||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "temp_testdir"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "921f1e9c427802414907a48b21a6504ff6b3a15a1a3cf37e699590949ad9befc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
members = [
|
members = [
|
||||||
"crates/tabby",
|
"crates/tabby",
|
||||||
"crates/tabby-common",
|
"crates/tabby-common",
|
||||||
|
"crates/tabby-scheduler",
|
||||||
"crates/ctranslate2-bindings",
|
"crates/ctranslate2-bindings",
|
||||||
"crates/rust-cxx-cmake-bridge",
|
"crates/rust-cxx-cmake-bridge",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ name = "tabby-common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.26"
|
chrono = "0.4.26"
|
||||||
lazy_static = { workspace = true }
|
lazy_static = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serdeconv = { workspace = true }
|
serdeconv = { workspace = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
testutils = []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[cfg_attr(feature = "testutils", derive(Serialize))]
|
||||||
|
pub struct Config {
|
||||||
|
pub repositories: Vec<Repository>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn load() -> Self {
|
||||||
|
serdeconv::from_toml_file(crate::path::config_file().as_path())
|
||||||
|
.expect("Failed to read config file")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "testutils")]
|
||||||
|
pub fn save(&self) {
|
||||||
|
let config_file = crate::path::config_file();
|
||||||
|
std::fs::create_dir_all(config_file.parent().unwrap()).unwrap();
|
||||||
|
serdeconv::to_toml_file(self, config_file).expect("Failed to write config file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Repository {
|
||||||
|
pub git_url: String,
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ use std::sync::Mutex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref WRITER: Mutex<BufWriter<fs::File>> = {
|
static ref WRITER: Mutex<BufWriter<fs::File>> = {
|
||||||
let events_dir = &crate::path::EVENTS_DIR;
|
let events_dir = crate::path::events_dir();
|
||||||
std::fs::create_dir_all(events_dir.as_path()).ok();
|
std::fs::create_dir_all(events_dir.as_path()).ok();
|
||||||
|
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
|
pub mod config;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,52 @@
|
||||||
|
use std::cell::Cell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref TABBY_ROOT: PathBuf = {
|
static ref TABBY_ROOT: Mutex<Cell<PathBuf>> = {
|
||||||
match env::var("TABBY_ROOT") {
|
Mutex::new(Cell::new(match env::var("TABBY_ROOT") {
|
||||||
Ok(x) => PathBuf::from(x),
|
Ok(x) => PathBuf::from(x),
|
||||||
Err(_) => PathBuf::from(env::var("HOME").unwrap()).join(".tabby"),
|
Err(_) => PathBuf::from(env::var("HOME").unwrap()).join(".tabby"),
|
||||||
}
|
}))
|
||||||
};
|
};
|
||||||
pub static ref EVENTS_DIR: PathBuf = TABBY_ROOT.join("events");
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "testutils")]
|
||||||
|
pub fn set_tabby_root(path: PathBuf) {
|
||||||
|
println!("SET TABBY ROOT: '{}'", path.display());
|
||||||
|
let cell = TABBY_ROOT.lock().unwrap();
|
||||||
|
cell.replace(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tabby_root() -> PathBuf {
|
||||||
|
let mut cell = TABBY_ROOT.lock().unwrap();
|
||||||
|
cell.get_mut().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config_file() -> PathBuf {
|
||||||
|
tabby_root().join("config.toml")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn repositories_dir() -> PathBuf {
|
||||||
|
tabby_root().join("repositories")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn models_dir() -> PathBuf {
|
||||||
|
tabby_root().join("models")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn events_dir() -> PathBuf {
|
||||||
|
tabby_root().join("events")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModelDir(PathBuf);
|
pub struct ModelDir(PathBuf);
|
||||||
|
|
||||||
impl ModelDir {
|
impl ModelDir {
|
||||||
pub fn new(model: &str) -> Self {
|
pub fn new(model: &str) -> Self {
|
||||||
Self(TABBY_ROOT.join("models").join(model))
|
Self(models_dir().join(model))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(path: &str) -> Self {
|
pub fn from(path: &str) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "tabby-scheduler"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
filenamify = "0.1.0"
|
||||||
|
tabby-common = { path = "../tabby-common" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
temp_testdir = "0.2"
|
||||||
|
tabby-common = { path = "../tabby-common", features = [ "testutils" ] }
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use tabby_common::{
|
||||||
|
config::{Config, Repository},
|
||||||
|
path::repositories_dir,
|
||||||
|
};
|
||||||
|
|
||||||
|
use filenamify::filenamify;
|
||||||
|
|
||||||
|
trait ConfigExt {
|
||||||
|
fn sync_repositories(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigExt for Config {
|
||||||
|
fn sync_repositories(&self) {
|
||||||
|
for repository in self.repositories.iter() {
|
||||||
|
repository.sync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait RepositoryExt {
|
||||||
|
fn dir(&self) -> PathBuf;
|
||||||
|
fn sync(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RepositoryExt for Repository {
|
||||||
|
fn dir(&self) -> PathBuf {
|
||||||
|
repositories_dir().join(filenamify(&self.git_url))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync(&self) {
|
||||||
|
let dir = self.dir();
|
||||||
|
let dir_string = dir.display().to_string();
|
||||||
|
let status = if dir.exists() {
|
||||||
|
Command::new("git")
|
||||||
|
.current_dir(&dir)
|
||||||
|
.arg("pull")
|
||||||
|
.status()
|
||||||
|
.expect("git could not be executed")
|
||||||
|
} else {
|
||||||
|
std::fs::create_dir_all(&dir)
|
||||||
|
.unwrap_or_else(|_| panic!("Failed to create dir {}", dir_string));
|
||||||
|
Command::new("git")
|
||||||
|
.current_dir(dir.parent().unwrap())
|
||||||
|
.arg("clone")
|
||||||
|
.arg("--depth")
|
||||||
|
.arg("1")
|
||||||
|
.arg(&self.git_url)
|
||||||
|
.arg(dir)
|
||||||
|
.status()
|
||||||
|
.expect("git could not be executed")
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(code) = status.code() {
|
||||||
|
if code != 0 {
|
||||||
|
panic!(
|
||||||
|
"Failed to pull remote '{}'\nConsider remove dir '{}' and retry",
|
||||||
|
&self.git_url, &dir_string
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn job_sync_repositories() {
|
||||||
|
let config = Config::load();
|
||||||
|
config.sync_repositories();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
use tabby_scheduler::*;
|
||||||
|
use temp_testdir::*;
|
||||||
|
|
||||||
|
use tabby_common::config::{Config, Repository};
|
||||||
|
use tabby_common::path::set_tabby_root;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
set_tabby_root(TempDir::default().to_path_buf());
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
repositories: vec![Repository {
|
||||||
|
git_url: "https://github.com/TabbyML/interview-questions".to_owned(),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
config.save();
|
||||||
|
job_sync_repositories()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue