Compare commits
3 Commits
34680f0087
...
597095a283
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
597095a283 | ||
|
|
d0e88abe85 | ||
|
|
cb6894798e |
@@ -97,11 +97,14 @@ pub fn run_me(config: &Config, args: &MeArgs, robot_mode: bool) -> Result<()> {
|
||||
let single_project = project_ids.len() == 1;
|
||||
|
||||
// 5. Parse --since (default 30d for activity feed, AC-2.3)
|
||||
let since_ms = args
|
||||
.since
|
||||
.as_deref()
|
||||
.and_then(parse_since)
|
||||
.unwrap_or_else(|| crate::core::time::now_ms() - DEFAULT_ACTIVITY_SINCE_DAYS * MS_PER_DAY);
|
||||
let since_ms = match args.since.as_deref() {
|
||||
Some(raw) => parse_since(raw).ok_or_else(|| {
|
||||
LoreError::Other(format!(
|
||||
"Invalid --since value '{raw}'. Expected: 7d, 2w, 3m, YYYY-MM-DD, or Unix-ms timestamp."
|
||||
))
|
||||
})?,
|
||||
None => crate::core::time::now_ms() - DEFAULT_ACTIVITY_SINCE_DAYS * MS_PER_DAY,
|
||||
};
|
||||
|
||||
// 6. Determine which sections to query
|
||||
let show_all = args.show_all_sections();
|
||||
@@ -184,7 +187,7 @@ pub fn run_me(config: &Config, args: &MeArgs, robot_mode: bool) -> Result<()> {
|
||||
|
||||
if robot_mode {
|
||||
let fields = args.fields.as_deref();
|
||||
render_robot::print_me_json(&dashboard, elapsed_ms, fields);
|
||||
render_robot::print_me_json(&dashboard, elapsed_ms, fields)?;
|
||||
} else if show_all {
|
||||
render_human::print_me_dashboard(&dashboard, single_project);
|
||||
} else {
|
||||
|
||||
@@ -10,6 +10,9 @@ use crate::core::error::Result;
|
||||
|
||||
use super::types::{ActivityEventType, AttentionState, MeActivityEvent, MeIssue, MeMr};
|
||||
|
||||
/// Stale threshold: items with no activity for 30 days are marked "stale".
|
||||
const STALE_THRESHOLD_MS: i64 = 30 * 24 * 3600 * 1000;
|
||||
|
||||
// ─── Open Issues (AC-5.1, Task #7) ─────────────────────────────────────────
|
||||
|
||||
/// Query open issues assigned to the user via issue_assignees.
|
||||
@@ -23,62 +26,47 @@ pub fn query_open_issues(
|
||||
let project_clause = build_project_clause("i.project_id", project_ids);
|
||||
|
||||
let sql = format!(
|
||||
"WITH my_latest AS (
|
||||
SELECT d.issue_id, MAX(n.created_at) AS ts
|
||||
"WITH note_ts AS (
|
||||
SELECT d.issue_id,
|
||||
MAX(CASE WHEN n.author_username = ?1 THEN n.created_at END) AS my_ts,
|
||||
MAX(CASE WHEN n.author_username != ?1 THEN n.created_at END) AS others_ts,
|
||||
MAX(n.created_at) AS any_ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username = ?1 AND n.is_system = 0
|
||||
AND d.issue_id IS NOT NULL
|
||||
GROUP BY d.issue_id
|
||||
),
|
||||
others_latest AS (
|
||||
SELECT d.issue_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username != ?1 AND n.is_system = 0
|
||||
AND d.issue_id IS NOT NULL
|
||||
GROUP BY d.issue_id
|
||||
),
|
||||
any_latest AS (
|
||||
SELECT d.issue_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.is_system = 0
|
||||
AND d.issue_id IS NOT NULL
|
||||
WHERE n.is_system = 0 AND d.issue_id IS NOT NULL
|
||||
GROUP BY d.issue_id
|
||||
)
|
||||
SELECT i.iid, i.title, p.path_with_namespace, i.status_name, i.updated_at, i.web_url,
|
||||
CASE
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts)
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts)
|
||||
THEN 'needs_attention'
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000)
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms})
|
||||
THEN 'stale'
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0)
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0)
|
||||
THEN 'awaiting_response'
|
||||
ELSE 'not_started'
|
||||
END AS attention_state
|
||||
FROM issues i
|
||||
JOIN issue_assignees ia ON ia.issue_id = i.id
|
||||
JOIN projects p ON i.project_id = p.id
|
||||
LEFT JOIN my_latest ml ON ml.issue_id = i.id
|
||||
LEFT JOIN others_latest ol ON ol.issue_id = i.id
|
||||
LEFT JOIN any_latest al ON al.issue_id = i.id
|
||||
LEFT JOIN note_ts nt ON nt.issue_id = i.id
|
||||
WHERE ia.username = ?1
|
||||
AND i.state = 'opened'
|
||||
{project_clause}
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts)
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts)
|
||||
THEN 0
|
||||
WHEN al.ts IS NULL AND ml.ts IS NULL
|
||||
WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL
|
||||
THEN 1
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000)
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms})
|
||||
THEN 3
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0)
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0)
|
||||
THEN 2
|
||||
ELSE 1
|
||||
END,
|
||||
i.updated_at DESC"
|
||||
i.updated_at DESC",
|
||||
stale_ms = STALE_THRESHOLD_MS,
|
||||
);
|
||||
|
||||
let params = build_params(username, project_ids);
|
||||
@@ -115,28 +103,14 @@ pub fn query_authored_mrs(
|
||||
let project_clause = build_project_clause("m.project_id", project_ids);
|
||||
|
||||
let sql = format!(
|
||||
"WITH my_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
"WITH note_ts AS (
|
||||
SELECT d.merge_request_id,
|
||||
MAX(CASE WHEN n.author_username = ?1 THEN n.created_at END) AS my_ts,
|
||||
MAX(CASE WHEN n.author_username != ?1 THEN n.created_at END) AS others_ts,
|
||||
MAX(n.created_at) AS any_ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username = ?1 AND n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
),
|
||||
others_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username != ?1 AND n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
),
|
||||
any_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
WHERE n.is_system = 0 AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
)
|
||||
SELECT m.iid, m.title, p.path_with_namespace, m.draft, m.detailed_merge_status,
|
||||
@@ -145,32 +119,31 @@ pub fn query_authored_mrs(
|
||||
WHEN m.draft = 1 AND NOT EXISTS (
|
||||
SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id
|
||||
) THEN 'not_ready'
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts)
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts)
|
||||
THEN 'needs_attention'
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000)
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms})
|
||||
THEN 'stale'
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0)
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0)
|
||||
THEN 'awaiting_response'
|
||||
ELSE 'not_started'
|
||||
END AS attention_state
|
||||
FROM merge_requests m
|
||||
JOIN projects p ON m.project_id = p.id
|
||||
LEFT JOIN my_latest ml ON ml.merge_request_id = m.id
|
||||
LEFT JOIN others_latest ol ON ol.merge_request_id = m.id
|
||||
LEFT JOIN any_latest al ON al.merge_request_id = m.id
|
||||
LEFT JOIN note_ts nt ON nt.merge_request_id = m.id
|
||||
WHERE m.author_username = ?1
|
||||
AND m.state = 'opened'
|
||||
{project_clause}
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN m.draft = 1 AND NOT EXISTS (SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id) THEN 4
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts) THEN 0
|
||||
WHEN al.ts IS NULL AND ml.ts IS NULL THEN 1
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000) THEN 3
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0) THEN 2
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) THEN 0
|
||||
WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL THEN 1
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 3
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 2
|
||||
ELSE 1
|
||||
END,
|
||||
m.updated_at DESC"
|
||||
m.updated_at DESC",
|
||||
stale_ms = STALE_THRESHOLD_MS,
|
||||
);
|
||||
|
||||
let params = build_params(username, project_ids);
|
||||
@@ -209,63 +182,45 @@ pub fn query_reviewing_mrs(
|
||||
let project_clause = build_project_clause("m.project_id", project_ids);
|
||||
|
||||
let sql = format!(
|
||||
"WITH my_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
"WITH note_ts AS (
|
||||
SELECT d.merge_request_id,
|
||||
MAX(CASE WHEN n.author_username = ?1 THEN n.created_at END) AS my_ts,
|
||||
MAX(CASE WHEN n.author_username != ?1 THEN n.created_at END) AS others_ts,
|
||||
MAX(n.created_at) AS any_ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username = ?1 AND n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
),
|
||||
others_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.author_username != ?1 AND n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
),
|
||||
any_latest AS (
|
||||
SELECT d.merge_request_id, MAX(n.created_at) AS ts
|
||||
FROM notes n
|
||||
JOIN discussions d ON n.discussion_id = d.id
|
||||
WHERE n.is_system = 0
|
||||
AND d.merge_request_id IS NOT NULL
|
||||
WHERE n.is_system = 0 AND d.merge_request_id IS NOT NULL
|
||||
GROUP BY d.merge_request_id
|
||||
)
|
||||
SELECT m.iid, m.title, p.path_with_namespace, m.draft, m.detailed_merge_status,
|
||||
m.author_username, m.updated_at, m.web_url,
|
||||
CASE
|
||||
WHEN m.draft = 1 AND NOT EXISTS (
|
||||
SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id
|
||||
) THEN 'not_ready'
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts)
|
||||
-- not_ready is impossible here: JOIN mr_reviewers guarantees a reviewer exists
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts)
|
||||
THEN 'needs_attention'
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000)
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms})
|
||||
THEN 'stale'
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0)
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0)
|
||||
THEN 'awaiting_response'
|
||||
ELSE 'not_started'
|
||||
END AS attention_state
|
||||
FROM merge_requests m
|
||||
JOIN mr_reviewers r ON r.merge_request_id = m.id
|
||||
JOIN projects p ON m.project_id = p.id
|
||||
LEFT JOIN my_latest ml ON ml.merge_request_id = m.id
|
||||
LEFT JOIN others_latest ol ON ol.merge_request_id = m.id
|
||||
LEFT JOIN any_latest al ON al.merge_request_id = m.id
|
||||
LEFT JOIN note_ts nt ON nt.merge_request_id = m.id
|
||||
WHERE r.username = ?1
|
||||
AND m.state = 'opened'
|
||||
{project_clause}
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN m.draft = 1 AND NOT EXISTS (SELECT 1 FROM mr_reviewers WHERE merge_request_id = m.id) THEN 4
|
||||
WHEN ol.ts IS NOT NULL AND (ml.ts IS NULL OR ol.ts > ml.ts) THEN 0
|
||||
WHEN al.ts IS NULL AND ml.ts IS NULL THEN 1
|
||||
WHEN al.ts IS NOT NULL AND al.ts < (strftime('%s', 'now') * 1000 - 30 * 24 * 3600 * 1000) THEN 3
|
||||
WHEN ml.ts IS NOT NULL AND ml.ts >= COALESCE(ol.ts, 0) THEN 2
|
||||
WHEN nt.others_ts IS NOT NULL AND (nt.my_ts IS NULL OR nt.others_ts > nt.my_ts) THEN 0
|
||||
WHEN nt.any_ts IS NULL AND nt.my_ts IS NULL THEN 1
|
||||
WHEN nt.any_ts IS NOT NULL AND nt.any_ts < (strftime('%s', 'now') * 1000 - {stale_ms}) THEN 3
|
||||
WHEN nt.my_ts IS NOT NULL AND nt.my_ts >= COALESCE(nt.others_ts, 0) THEN 2
|
||||
ELSE 1
|
||||
END,
|
||||
m.updated_at DESC"
|
||||
m.updated_at DESC",
|
||||
stale_ms = STALE_THRESHOLD_MS,
|
||||
);
|
||||
|
||||
let params = build_params(username, project_ids);
|
||||
@@ -552,7 +507,7 @@ fn build_params(username: &str, project_ids: &[i64]) -> Vec<Box<dyn rusqlite::ty
|
||||
params
|
||||
}
|
||||
|
||||
/// Populate labels for issues (avoids N+1 when there are few issues).
|
||||
/// Populate labels for issues via cached per-item queries.
|
||||
fn populate_issue_labels(conn: &Connection, issues: &mut [MeIssue]) -> Result<()> {
|
||||
if issues.is_empty() {
|
||||
return Ok(());
|
||||
@@ -576,7 +531,7 @@ fn populate_issue_labels(conn: &Connection, issues: &mut [MeIssue]) -> Result<()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Populate labels for MRs (avoids N+1 when there are few MRs).
|
||||
/// Populate labels for MRs via cached per-item queries.
|
||||
fn populate_mr_labels(conn: &Connection, mrs: &mut [MeMr]) -> Result<()> {
|
||||
if mrs.is_empty() {
|
||||
return Ok(());
|
||||
|
||||
@@ -138,6 +138,7 @@ fn print_attention_legend() {
|
||||
(AttentionState::NotStarted, "not started"),
|
||||
(AttentionState::AwaitingResponse, "awaiting response"),
|
||||
(AttentionState::Stale, "stale (30d+)"),
|
||||
(AttentionState::NotReady, "draft (not ready)"),
|
||||
];
|
||||
|
||||
let legend: Vec<String> = states
|
||||
@@ -369,7 +370,7 @@ fn format_entity_ref(entity_type: &str, iid: i64) -> String {
|
||||
let s = format!("#{iid}");
|
||||
Theme::issue_ref().render(&s)
|
||||
}
|
||||
"merge_request" => {
|
||||
"mr" => {
|
||||
let s = format!("!{iid}");
|
||||
Theme::mr_ref().render(&s)
|
||||
}
|
||||
@@ -440,7 +441,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn format_entity_ref_mr() {
|
||||
let result = format_entity_ref("merge_request", 99);
|
||||
let result = format_entity_ref("mr", 99);
|
||||
assert!(result.contains("99"), "got: {result}");
|
||||
}
|
||||
|
||||
|
||||
@@ -10,20 +10,19 @@ use super::types::{
|
||||
// ─── Robot JSON Output (Task #18) ────────────────────────────────────────────
|
||||
|
||||
/// Print the full me dashboard as robot-mode JSON.
|
||||
pub fn print_me_json(dashboard: &MeDashboard, elapsed_ms: u64, fields: Option<&[String]>) {
|
||||
pub fn print_me_json(
|
||||
dashboard: &MeDashboard,
|
||||
elapsed_ms: u64,
|
||||
fields: Option<&[String]>,
|
||||
) -> crate::core::error::Result<()> {
|
||||
let envelope = MeJsonEnvelope {
|
||||
ok: true,
|
||||
data: MeDataJson::from_dashboard(dashboard),
|
||||
meta: RobotMeta { elapsed_ms },
|
||||
};
|
||||
|
||||
let mut value = match serde_json::to_value(&envelope) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("Error serializing me JSON: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut value = serde_json::to_value(&envelope)
|
||||
.map_err(|e| crate::core::error::LoreError::Other(format!("JSON serialization: {e}")))?;
|
||||
|
||||
// Apply --fields filtering (Task #19)
|
||||
if let Some(f) = fields {
|
||||
@@ -38,10 +37,10 @@ pub fn print_me_json(dashboard: &MeDashboard, elapsed_ms: u64, fields: Option<&[
|
||||
crate::cli::robot::filter_fields(&mut value, "activity", &activity_expanded);
|
||||
}
|
||||
|
||||
match serde_json::to_string(&value) {
|
||||
Ok(json) => println!("{json}"),
|
||||
Err(e) => eprintln!("Error serializing to JSON: {e}"),
|
||||
}
|
||||
let json = serde_json::to_string(&value)
|
||||
.map_err(|e| crate::core::error::LoreError::Other(format!("JSON serialization: {e}")))?;
|
||||
println!("{json}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ─── JSON Envelope ───────────────────────────────────────────────────────────
|
||||
|
||||
@@ -168,7 +168,6 @@ fn test_ingest_issue_by_iid_upserts_and_marks_dirty() {
|
||||
|
||||
let result = ingest_issue_by_iid(&conn, &config, 1, &issue).unwrap();
|
||||
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.dirty_source_keys.is_empty());
|
||||
|
||||
@@ -200,7 +199,6 @@ fn test_toctou_skips_stale_issue() {
|
||||
// Second ingest with same timestamp should be skipped
|
||||
let r2 = ingest_issue_by_iid(&conn, &config, 1, &issue).unwrap();
|
||||
assert!(r2.skipped_stale);
|
||||
assert!(r2.skipped_stale);
|
||||
assert!(r2.dirty_source_keys.is_empty());
|
||||
|
||||
// No new dirty mark
|
||||
@@ -224,7 +222,6 @@ fn test_toctou_allows_newer_issue() {
|
||||
let result = ingest_issue_by_iid(&conn, &config, 1, &issue_t2).unwrap();
|
||||
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.skipped_stale);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -272,7 +269,6 @@ fn test_ingest_mr_by_iid_upserts_and_marks_dirty() {
|
||||
|
||||
let result = ingest_mr_by_iid(&conn, &config, 1, &mr).unwrap();
|
||||
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.dirty_source_keys.is_empty());
|
||||
|
||||
@@ -299,7 +295,6 @@ fn test_toctou_skips_stale_mr() {
|
||||
|
||||
let r2 = ingest_mr_by_iid(&conn, &config, 1, &mr).unwrap();
|
||||
assert!(r2.skipped_stale);
|
||||
assert!(r2.skipped_stale);
|
||||
assert!(r2.dirty_source_keys.is_empty());
|
||||
}
|
||||
|
||||
@@ -317,7 +312,6 @@ fn test_toctou_allows_newer_mr() {
|
||||
let result = ingest_mr_by_iid(&conn, &config, 1, &mr_t2).unwrap();
|
||||
|
||||
assert!(!result.skipped_stale);
|
||||
assert!(!result.skipped_stale);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user