mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
Track scheduler affinity epochs and key sorting
This commit is contained in:
@@ -516,6 +516,10 @@ pub enum ProviderCatalogKeyListOrder {
|
||||
#[default]
|
||||
Name,
|
||||
CreatedAt,
|
||||
CreatedAtAsc,
|
||||
CreatedAtDesc,
|
||||
LastUsedAtAsc,
|
||||
LastUsedAtDesc,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
|
||||
@@ -2657,6 +2657,22 @@ CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_active ON public.provi
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_created_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_created_at_desc ON public.provider_api_keys USING btree (provider_id, created_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_last_used_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_last_used_at_desc ON public.provider_api_keys USING btree (provider_id, last_used_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_created_at_desc
|
||||
ON public.provider_api_keys USING btree (provider_id, created_at DESC NULLS LAST, name, id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_last_used_at_desc
|
||||
ON public.provider_api_keys USING btree (provider_id, last_used_at DESC NULLS LAST, name, id);
|
||||
@@ -133,6 +133,22 @@ CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_active ON public.provi
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_created_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_created_at_desc ON public.provider_api_keys USING btree (provider_id, created_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_last_used_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_last_used_at_desc ON public.provider_api_keys USING btree (provider_id, last_used_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -125,6 +125,22 @@ CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_active ON public.provi
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_created_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_created_at_desc ON public.provider_api_keys USING btree (provider_id, created_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_last_used_at_desc; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provider_api_keys_provider_last_used_at_desc ON public.provider_api_keys USING btree (provider_id, last_used_at DESC NULLS LAST, name, id);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_provider_api_keys_provider_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -7,7 +7,7 @@ use tracing::info;
|
||||
// Generated by build.rs from schema/bootstrap/postgres.
|
||||
pub(crate) static EMPTY_DATABASE_SNAPSHOT_SQL: &str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/empty_database_snapshot.sql"));
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260510120000;
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260511000000;
|
||||
|
||||
const PUBLIC_BASE_TABLE_COUNT_SQL: &str = r#"
|
||||
SELECT COUNT(*)::BIGINT
|
||||
|
||||
@@ -298,6 +298,7 @@ fn empty_database_snapshot_covers_current_cutoff_versions() {
|
||||
20260509120000,
|
||||
20260510000000,
|
||||
20260510120000,
|
||||
20260511000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -1082,6 +1083,7 @@ fn pending_migrations_from_applied_skips_versions_already_applied() {
|
||||
20260509120000,
|
||||
20260510000000,
|
||||
20260510120000,
|
||||
20260511000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::RwLock;
|
||||
|
||||
@@ -454,6 +455,20 @@ impl ProviderCatalogReadRepository for InMemoryProviderCatalogReadRepository {
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
fn compare_optional_u64_null_last(
|
||||
left: Option<u64>,
|
||||
right: Option<u64>,
|
||||
descending: bool,
|
||||
) -> Ordering {
|
||||
match (left, right) {
|
||||
(Some(left), Some(right)) if descending => right.cmp(&left),
|
||||
(Some(left), Some(right)) => left.cmp(&right),
|
||||
(Some(_), None) => Ordering::Less,
|
||||
(None, Some(_)) => Ordering::Greater,
|
||||
(None, None) => Ordering::Equal,
|
||||
}
|
||||
}
|
||||
|
||||
match query.order {
|
||||
ProviderCatalogKeyListOrder::Name => {
|
||||
keys.sort_by(|left, right| {
|
||||
@@ -475,6 +490,50 @@ impl ProviderCatalogReadRepository for InMemoryProviderCatalogReadRepository {
|
||||
.then(left.id.cmp(&right.id))
|
||||
});
|
||||
}
|
||||
ProviderCatalogKeyListOrder::CreatedAtAsc => {
|
||||
keys.sort_by(|left, right| {
|
||||
compare_optional_u64_null_last(
|
||||
left.created_at_unix_ms,
|
||||
right.created_at_unix_ms,
|
||||
false,
|
||||
)
|
||||
.then(left.name.cmp(&right.name))
|
||||
.then(left.id.cmp(&right.id))
|
||||
});
|
||||
}
|
||||
ProviderCatalogKeyListOrder::CreatedAtDesc => {
|
||||
keys.sort_by(|left, right| {
|
||||
compare_optional_u64_null_last(
|
||||
left.created_at_unix_ms,
|
||||
right.created_at_unix_ms,
|
||||
true,
|
||||
)
|
||||
.then(left.name.cmp(&right.name))
|
||||
.then(left.id.cmp(&right.id))
|
||||
});
|
||||
}
|
||||
ProviderCatalogKeyListOrder::LastUsedAtAsc => {
|
||||
keys.sort_by(|left, right| {
|
||||
compare_optional_u64_null_last(
|
||||
left.last_used_at_unix_secs,
|
||||
right.last_used_at_unix_secs,
|
||||
false,
|
||||
)
|
||||
.then(left.name.cmp(&right.name))
|
||||
.then(left.id.cmp(&right.id))
|
||||
});
|
||||
}
|
||||
ProviderCatalogKeyListOrder::LastUsedAtDesc => {
|
||||
keys.sort_by(|left, right| {
|
||||
compare_optional_u64_null_last(
|
||||
left.last_used_at_unix_secs,
|
||||
right.last_used_at_unix_secs,
|
||||
true,
|
||||
)
|
||||
.then(left.name.cmp(&right.name))
|
||||
.then(left.id.cmp(&right.id))
|
||||
});
|
||||
}
|
||||
}
|
||||
let total = keys.len();
|
||||
let items = keys
|
||||
@@ -1028,6 +1087,70 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn paginates_provider_keys_by_pool_sort_fields() {
|
||||
let mut old = sample_key("key-1", "provider-1");
|
||||
old.name = "old".to_string();
|
||||
old.created_at_unix_ms = Some(10);
|
||||
old.last_used_at_unix_secs = Some(30);
|
||||
let mut fresh = sample_key("key-2", "provider-1");
|
||||
fresh.name = "fresh".to_string();
|
||||
fresh.created_at_unix_ms = Some(20);
|
||||
fresh.last_used_at_unix_secs = Some(10);
|
||||
let mut unused = sample_key("key-3", "provider-1");
|
||||
unused.name = "unused".to_string();
|
||||
unused.created_at_unix_ms = None;
|
||||
unused.last_used_at_unix_secs = None;
|
||||
let repository = InMemoryProviderCatalogReadRepository::seed(
|
||||
vec![sample_provider("provider-1")],
|
||||
vec![],
|
||||
vec![old, fresh, unused],
|
||||
);
|
||||
|
||||
let imported = repository
|
||||
.list_keys_page(&ProviderCatalogKeyListQuery {
|
||||
provider_id: "provider-1".to_string(),
|
||||
search: None,
|
||||
is_active: None,
|
||||
offset: 0,
|
||||
limit: 2,
|
||||
order: ProviderCatalogKeyListOrder::CreatedAtDesc,
|
||||
})
|
||||
.await
|
||||
.expect("keys should page");
|
||||
|
||||
assert_eq!(imported.total, 3);
|
||||
assert_eq!(
|
||||
imported
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| item.id.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec!["key-2", "key-1"]
|
||||
);
|
||||
|
||||
let last_used = repository
|
||||
.list_keys_page(&ProviderCatalogKeyListQuery {
|
||||
provider_id: "provider-1".to_string(),
|
||||
search: None,
|
||||
is_active: None,
|
||||
offset: 0,
|
||||
limit: 3,
|
||||
order: ProviderCatalogKeyListOrder::LastUsedAtDesc,
|
||||
})
|
||||
.await
|
||||
.expect("keys should page");
|
||||
|
||||
assert_eq!(
|
||||
last_used
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| item.id.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec!["key-1", "key-2", "key-3"]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn summarizes_provider_key_stats() {
|
||||
let mut inactive = sample_key("key-2", "provider-1");
|
||||
|
||||
@@ -571,6 +571,18 @@ ORDER BY provider_priority ASC, name ASC
|
||||
ProviderCatalogKeyListOrder::CreatedAt => {
|
||||
"internal_priority ASC, COALESCE(created_at, TO_TIMESTAMP(0)) ASC, id ASC"
|
||||
}
|
||||
ProviderCatalogKeyListOrder::CreatedAtAsc => {
|
||||
"created_at ASC NULLS LAST, name ASC, id ASC"
|
||||
}
|
||||
ProviderCatalogKeyListOrder::CreatedAtDesc => {
|
||||
"created_at DESC NULLS LAST, name ASC, id ASC"
|
||||
}
|
||||
ProviderCatalogKeyListOrder::LastUsedAtAsc => {
|
||||
"last_used_at ASC NULLS LAST, name ASC, id ASC"
|
||||
}
|
||||
ProviderCatalogKeyListOrder::LastUsedAtDesc => {
|
||||
"last_used_at DESC NULLS LAST, name ASC, id ASC"
|
||||
}
|
||||
};
|
||||
|
||||
let count_row = sqlx::query(
|
||||
|
||||
Reference in New Issue
Block a user