Files
kebab/crates/kebab-store-sqlite/tests/jobs.rs
altair823 911fb49550 refactor(rename): kb crates → kebab — Cargo packages, folders, Rust modules
프로젝트 이름 `kb` → `kebab` rename 의 첫 단계.

- workspace `Cargo.toml`: members `crates/kb-*` → `crates/kebab-*`,
  repository URL `altair823/kb` → `altair823/kebab`.
- 18 crate 폴더 rename via `git mv` (history 보존).
- 각 crate `Cargo.toml`: `name = "kb-*"` → `"kebab-*"`, path deps
  `../kb-*` → `../kebab-*`.
- 모든 `.rs`: `kb_<id>` snake-case 모듈 path 18 개 (`kb_core`,
  `kb_config`, `kb_app`, `kb_cli`, `kb_eval`, `kb_search`, `kb_chunk`,
  `kb_normalize`, `kb_source_fs`, `kb_parse_md`, `kb_parse_types`,
  `kb_store_sqlite`, `kb_store_vector`, `kb_embed`, `kb_embed_local`,
  `kb_llm`, `kb_llm_local`, `kb_rag`) → `kebab_<id>` 일괄 sed (단어
  경계 \\b 사용해 영어 문장 안의 "kb" 약어 미오염).

CLI binary 이름 (`[[bin]] name = "kb"`), 환경변수 `KB_*`, XDG paths,
tracing target, 그리고 docs sweep 은 다음 commit 에서.

## 검증

- `cargo check --workspace` clean — 모든 crate 빌드 통과 후 commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 03:28:08 +00:00

91 lines
2.9 KiB
Rust

//! `JobRepo` smoke tests: create → progress → finish, list filters.
use kebab_core::{JobFilter, JobKind, JobRepo, JobStatus};
use kebab_store_sqlite::SqliteStore;
use serde_json::json;
mod common;
#[test]
fn create_then_progress_then_finish() {
let env = common::TestEnv::new();
let store = SqliteStore::open(&env.config()).unwrap();
store.run_migrations().unwrap();
let id = store
.create(JobKind::Ingest, json!({"path": "notes/x.md"}))
.unwrap();
// Status starts pending.
let row = store.list(&JobFilter::default()).unwrap();
assert_eq!(row.len(), 1);
assert_eq!(row[0].status, JobStatus::Pending);
// First progress flips pending → running.
store
.update_progress(&id, json!({"processed": 1, "total": 10}))
.unwrap();
let row = store.list(&JobFilter::default()).unwrap();
assert_eq!(row[0].status, JobStatus::Running);
assert_eq!(row[0].progress.as_ref().unwrap()["total"], json!(10));
// Finish with success.
store
.finish(&id, JobStatus::Succeeded, None)
.unwrap();
let row = store.list(&JobFilter::default()).unwrap();
assert_eq!(row[0].status, JobStatus::Succeeded);
assert!(row[0].finished_at.is_some());
assert!(row[0].error.is_none());
}
#[test]
fn finish_with_error_message_is_round_trippable() {
let env = common::TestEnv::new();
let store = SqliteStore::open(&env.config()).unwrap();
store.run_migrations().unwrap();
let id = store.create(JobKind::Embed, json!({})).unwrap();
store
.finish(&id, JobStatus::Failed, Some("boom: model not pulled"))
.unwrap();
let row = store.list(&JobFilter::default()).unwrap();
assert_eq!(row[0].status, JobStatus::Failed);
assert_eq!(
row[0].error.as_deref(),
Some("boom: model not pulled"),
"error message must round-trip"
);
}
#[test]
fn list_filters_status_and_kind() {
let env = common::TestEnv::new();
let store = SqliteStore::open(&env.config()).unwrap();
store.run_migrations().unwrap();
// Two ingest jobs (one finished succeeded, one pending) + one embed.
let a = store.create(JobKind::Ingest, json!({"a": 1})).unwrap();
let _b = store.create(JobKind::Ingest, json!({"b": 1})).unwrap();
let _c = store.create(JobKind::Embed, json!({"c": 1})).unwrap();
store.finish(&a, JobStatus::Succeeded, None).unwrap();
let by_status_succeeded = store
.list(&JobFilter {
status: Some(JobStatus::Succeeded),
kind: None,
})
.unwrap();
assert_eq!(by_status_succeeded.len(), 1);
assert_eq!(by_status_succeeded[0].kind, JobKind::Ingest);
let by_kind_embed = store
.list(&JobFilter {
status: None,
kind: Some(JobKind::Embed),
})
.unwrap();
assert_eq!(by_kind_embed.len(), 1);
assert_eq!(by_kind_embed[0].kind, JobKind::Embed);
}