From e4364e1c4427aae02ca4a7614114d5e11b045e96 Mon Sep 17 00:00:00 2001 From: Priec Date: Mon, 7 Sep 2026 09:54:32 +0200 Subject: [PATCH] new enum instead of string in proto --- client | 2 +- client-gui2 | 2 +- common/proto/search.proto | 8 +++- common/proto/table_definition.proto | 10 ++++- common/src/proto/descriptor.bin | Bin 249740 -> 250444 bytes common/src/proto/komp_ac.search.rs | 34 +++++++++++++++- common/src/proto/komp_ac.table_definition.rs | 38 ++++++++++++++++-- server | 2 +- web/src/pages/add_table/loader.rs | 9 +++-- web/src/pages/admin/admin/loader.rs | 9 +++-- web/src/pages/admin/admin/state.rs | 4 +- web/src/pages/admin/admin/ui.rs | 4 +- .../pages/admin/table_definition/loader.rs | 10 ++--- web/src/pages/admin/table_definition/state.rs | 4 +- web/src/pages/admin/table_definition/ui.rs | 16 ++++---- web/src/pages/table_scope.rs | 10 ++++- 16 files changed, 122 insertions(+), 40 deletions(-) diff --git a/client b/client index 4ef069e7..dc88add4 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 4ef069e7b1972dd4b4e7fdb2bb6db6512eda29c3 +Subproject commit dc88add49e3cdb51f832d6768465a90b94a8ad51 diff --git a/client-gui2 b/client-gui2 index 782877f6..965938b5 160000 --- a/client-gui2 +++ b/client-gui2 @@ -1 +1 @@ -Subproject commit 782877f62aa4523c6c1dee718b38b3c611c5dad4 +Subproject commit 965938b510f238bd848fcccf68686ad1b98a0ad3 diff --git a/common/proto/search.proto b/common/proto/search.proto index 2418b78a..508356b1 100644 --- a/common/proto/search.proto +++ b/common/proto/search.proto @@ -47,12 +47,18 @@ message ReindexResponse { uint64 affected_tables = 2; } +enum SearchIndexOperation { + SEARCH_INDEX_OPERATION_UNSPECIFIED = 0; + SEARCH_INDEX_OPERATION_UPSERT = 1; + SEARCH_INDEX_OPERATION_DELETE = 2; +} + message SearchIndexError { int64 job_id = 1; string profile_name = 2; string table_name = 3; int64 row_id = 4; - string operation = 5; + SearchIndexOperation operation = 5; int32 attempts = 6; string last_error = 7; } diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 3e1281e2..8c37b5ee 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -437,7 +437,7 @@ message ProfileTreeResponse { repeated string row_display_columns = 4; // "dynamic" for user-defined tables, "system" for backend-managed tables. - string table_kind = 5; + ManagedTableKind table_kind = 5; // True when this table is shared by every profile. bool global = 6; @@ -590,6 +590,12 @@ message GetAliasChangeHistoryResponse { repeated AliasChangeHistoryEntry entries = 2; } +enum ManagedTableKind { + MANAGED_TABLE_KIND_UNSPECIFIED = 0; + MANAGED_TABLE_KIND_DYNAMIC = 1; + MANAGED_TABLE_KIND_SYSTEM = 2; +} + // Describes a table with its columns and associated scripts. message TableDetail { string name = 1; @@ -598,7 +604,7 @@ message TableDetail { repeated ScriptInfo scripts = 4; repeated string row_display_columns = 6; map column_behaviors = 7; - string table_kind = 8; + ManagedTableKind table_kind = 8; bool global = 9; // Revision of this table definition for optimistic concurrency control. int64 row_version = 10; diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 9f81056d0bafd0a2d2e68f3af6d7790642c4f942..37f665a61508926e44ca426bc3bcfcbe25120fae 100644 GIT binary patch delta 11272 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 &'static str { + match self { + Self::Unspecified => "SEARCH_INDEX_OPERATION_UNSPECIFIED", + Self::Upsert => "SEARCH_INDEX_OPERATION_UPSERT", + Self::Delete => "SEARCH_INDEX_OPERATION_DELETE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SEARCH_INDEX_OPERATION_UNSPECIFIED" => Some(Self::Unspecified), + "SEARCH_INDEX_OPERATION_UPSERT" => Some(Self::Upsert), + "SEARCH_INDEX_OPERATION_DELETE" => Some(Self::Delete), + _ => None, + } + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] pub enum MatchMode { Unspecified = 0, Fuzzy = 1, diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index cde3e16f..e824406f 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -389,8 +389,8 @@ pub mod profile_tree_response { ::prost::alloc::string::String, >, /// "dynamic" for user-defined tables, "system" for backend-managed tables. - #[prost(string, tag = "5")] - pub table_kind: ::prost::alloc::string::String, + #[prost(enumeration = "super::ManagedTableKind", tag = "5")] + pub table_kind: i32, /// True when this table is shared by every profile. #[prost(bool, tag = "6")] pub global: bool, @@ -625,8 +625,8 @@ pub struct TableDetail { ::prost::alloc::string::String, ColumnBehavior, >, - #[prost(string, tag = "8")] - pub table_kind: ::prost::alloc::string::String, + #[prost(enumeration = "ManagedTableKind", tag = "8")] + pub table_kind: i32, #[prost(bool, tag = "9")] pub global: bool, /// Revision of this table definition for optimistic concurrency control. @@ -1156,6 +1156,36 @@ impl AliasChangeKind { } } } +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ManagedTableKind { + Unspecified = 0, + Dynamic = 1, + System = 2, +} +impl ManagedTableKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "MANAGED_TABLE_KIND_UNSPECIFIED", + Self::Dynamic => "MANAGED_TABLE_KIND_DYNAMIC", + Self::System => "MANAGED_TABLE_KIND_SYSTEM", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "MANAGED_TABLE_KIND_UNSPECIFIED" => Some(Self::Unspecified), + "MANAGED_TABLE_KIND_DYNAMIC" => Some(Self::Dynamic), + "MANAGED_TABLE_KIND_SYSTEM" => Some(Self::System), + _ => None, + } + } +} /// How a column type is spelled in ColumnDefinition.field_type. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] diff --git a/server b/server index c51ead9a..8dc36863 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit c51ead9a190add6150e10d96e34b1359c1d73306 +Subproject commit 8dc3686366c04119f37a896eddace84c8be97808 diff --git a/web/src/pages/add_table/loader.rs b/web/src/pages/add_table/loader.rs index 54e6f88e..01ccf4ae 100644 --- a/web/src/pages/add_table/loader.rs +++ b/web/src/pages/add_table/loader.rs @@ -112,12 +112,13 @@ pub(crate) async fn load_page( // The profile's ledger accounts are not a link target of their own: an // ACCOUNTING column is how a row is posted to one. .filter(|table| table.name != crate::schema::LEDGER_ACCOUNTS_TABLE) - .map(|table| RelationTableOption { + .map(|table| Ok(RelationTableOption { name: table.name, global: table.global, - system: table.table_kind == "system", - }) - .collect::>(); + system: table_scope::table_kind(table.table_kind).map_err(LoadError::Backend)? + == crate::definitions::table_definition::ManagedTableKind::System, + })) + .collect::, LoadError>>()?; // Every table the new one would sit beside holds its name — including the // shared ones, which exist in every profile, and including in a profile diff --git a/web/src/pages/admin/admin/loader.rs b/web/src/pages/admin/admin/loader.rs index 491bfd46..db1e29cf 100644 --- a/web/src/pages/admin/admin/loader.rs +++ b/web/src/pages/admin/admin/loader.rs @@ -101,7 +101,7 @@ pub(crate) async fn load_admin_page( .map(|tables| { tables .into_iter() - .map(|table| TableView { + .map(|table| Ok(TableView { name: table.name, // One entry per link, named by the column carrying it, so a // table pointing at one target twice reads as two links. @@ -113,10 +113,11 @@ pub(crate) async fn load_admin_page( }) .collect(), row_display_columns: table.row_display_columns, - table_kind: table.table_kind, - }) - .collect::>() + table_kind: table_scope::table_kind(table.table_kind).map_err(LoadError::Backend)?, + })) + .collect::, LoadError>>() }) + .transpose()? .unwrap_or_default(); let selected_table = (!selection.table.is_empty()).then_some(selection.table); diff --git a/web/src/pages/admin/admin/state.rs b/web/src/pages/admin/admin/state.rs index 4fe30b4d..665ae7ae 100644 --- a/web/src/pages/admin/admin/state.rs +++ b/web/src/pages/admin/admin/state.rs @@ -84,14 +84,14 @@ pub(crate) struct TableView { pub name: String, pub depends_on: Vec, pub row_display_columns: Vec, - pub table_kind: String, + pub table_kind: crate::definitions::table_definition::ManagedTableKind, } impl TableView { /// System tables are backend-managed: the server refuses every structural /// write on them, so the pane offers none of the action links for one. pub(crate) fn is_system(&self) -> bool { - self.table_kind == "system" + self.table_kind == crate::definitions::table_definition::ManagedTableKind::System } } diff --git a/web/src/pages/admin/admin/ui.rs b/web/src/pages/admin/admin/ui.rs index 02b4c9b4..f716b5e3 100644 --- a/web/src/pages/admin/admin/ui.rs +++ b/web/src/pages/admin/admin/ui.rs @@ -155,7 +155,7 @@ mod tests { name: "invoice".to_string(), depends_on: Vec::new(), row_display_columns: vec!["number".to_string()], - table_kind: "dynamic".to_string(), + table_kind: crate::definitions::table_definition::ManagedTableKind::Dynamic, }], selected_table: Some("invoice".to_string()), columns: Vec::new(), @@ -195,7 +195,7 @@ mod tests { name: "currencies".to_string(), depends_on: Vec::new(), row_display_columns: vec!["code".to_string()], - table_kind: "dynamic".to_string(), + table_kind: crate::definitions::table_definition::ManagedTableKind::Dynamic, }], selected_table: Some("currencies".to_string()), columns: Vec::new(), diff --git a/web/src/pages/admin/table_definition/loader.rs b/web/src/pages/admin/table_definition/loader.rs index 6e1ed01e..4f905a47 100644 --- a/web/src/pages/admin/table_definition/loader.rs +++ b/web/src/pages/admin/table_definition/loader.rs @@ -146,9 +146,9 @@ pub(crate) async fn load_page( } else { table_scope::linkable_tables(&tree.profiles, &catalog_tables, &inputs.selection.profile) }; - let summary = |table: crate::definitions::table_definition::profile_tree_response::Table| TableSummary { + let summary = |table: crate::definitions::table_definition::profile_tree_response::Table| -> Result { Ok(TableSummary { name: table.name, - table_kind: table.table_kind, + table_kind: table_scope::table_kind(table.table_kind).map_err(LoadError::Backend)?, global: table.global, // One entry per link, named by the column carrying it, so a table // pointing at one target twice reads as two links. @@ -157,9 +157,9 @@ pub(crate) async fn load_page( .into_iter() .map(|dependency| format!("{} ({})", dependency.table_name, dependency.column_name)) .collect(), - }; - let tables = selected_tables.into_iter().map(summary).collect::>(); - let link_targets = link_targets.into_iter().map(summary).collect::>(); + }) }; + let tables = selected_tables.into_iter().map(summary).collect::, _>>()?; + let link_targets = link_targets.into_iter().map(summary).collect::, _>>()?; // A table the scope does not hold is dropped rather than acted on. It is // said out loud, though: dropping it in silence is what left the panel diff --git a/web/src/pages/admin/table_definition/state.rs b/web/src/pages/admin/table_definition/state.rs index d6de9cca..1caf59e0 100644 --- a/web/src/pages/admin/table_definition/state.rs +++ b/web/src/pages/admin/table_definition/state.rs @@ -67,7 +67,7 @@ impl Selection { #[derive(Clone, Debug)] pub(crate) struct TableSummary { pub name: String, - pub table_kind: String, + pub table_kind: crate::definitions::table_definition::ManagedTableKind, pub global: bool, pub depends_on: Vec, } @@ -76,7 +76,7 @@ impl TableSummary { /// System tables are backend-managed: the server refuses every write below /// on them, so the workspace does not offer the panels either. pub(crate) fn is_system(&self) -> bool { - self.table_kind == "system" + self.table_kind == crate::definitions::table_definition::ManagedTableKind::System } } diff --git a/web/src/pages/admin/table_definition/ui.rs b/web/src/pages/admin/table_definition/ui.rs index 88d8eee4..74611a9d 100644 --- a/web/src/pages/admin/table_definition/ui.rs +++ b/web/src/pages/admin/table_definition/ui.rs @@ -247,10 +247,10 @@ mod tests { schema::ColumnDraft, }; - fn table(name: &str, kind: &str) -> TableSummary { + fn table(name: &str, kind: crate::definitions::table_definition::ManagedTableKind) -> TableSummary { TableSummary { name: name.to_string(), - table_kind: kind.to_string(), + table_kind: kind, global: false, depends_on: Vec::new(), } @@ -268,8 +268,8 @@ mod tests { profile: "billing".to_string(), table: "invoice".to_string(), }, - tables: vec![table("invoice", "dynamic"), table("ledger_accounts", "system")], - link_targets: vec![table("invoice", "dynamic"), table("ledger_accounts", "system")], + tables: vec![table("invoice", crate::definitions::table_definition::ManagedTableKind::Dynamic), table("ledger_accounts", crate::definitions::table_definition::ManagedTableKind::System)], + link_targets: vec![table("invoice", crate::definitions::table_definition::ManagedTableKind::Dynamic), table("ledger_accounts", crate::definitions::table_definition::ManagedTableKind::System)], detail: Some(TableDetailView { id: 7, row_version: 1, @@ -364,7 +364,7 @@ mod tests { }; state.tables = vec![TableSummary { name: "currencies".to_string(), - table_kind: "dynamic".to_string(), + table_kind: crate::definitions::table_definition::ManagedTableKind::Dynamic, global: true, depends_on: Vec::new(), }]; @@ -598,12 +598,12 @@ mod tests { state.columns.type_input = "link".to_string(); // The link targets are their own list: a profile's table may point at // a shared one, which is not among the profile's own tables. - state.link_targets.push(table("customer", "dynamic")); + state.link_targets.push(table("customer", crate::definitions::table_definition::ManagedTableKind::Dynamic)); state.link_targets.push(TableSummary { global: true, - ..table("currencies", "dynamic") + ..table("currencies", crate::definitions::table_definition::ManagedTableKind::Dynamic) }); - state.link_targets.push(table("audit_log", "system")); + state.link_targets.push(table("audit_log", crate::definitions::table_definition::ManagedTableKind::System)); let html = render_column_panel(&state); diff --git a/web/src/pages/table_scope.rs b/web/src/pages/table_scope.rs index 14f7fd7e..27c93fc4 100644 --- a/web/src/pages/table_scope.rs +++ b/web/src/pages/table_scope.rs @@ -13,6 +13,14 @@ //! profile's own tables are the tree's. Neither is derived from the other. use crate::definitions::table_definition::profile_tree_response::{Profile, Table}; +use crate::definitions::table_definition::ManagedTableKind; + +pub(crate) fn table_kind(value: i32) -> Result { + match ManagedTableKind::try_from(value) { + Ok(kind @ (ManagedTableKind::Dynamic | ManagedTableKind::System)) => Ok(kind), + _ => Err(format!("Invalid managed table kind: {value}")), + } +} /// The tables of the global scope: the catalog for `profile_name: None`, which /// is every shared table in the deployment, whether or not any profile exists @@ -74,7 +82,7 @@ pub(crate) mod tests { name: name.to_string(), depends_on: Vec::new(), row_display_columns: Vec::new(), - table_kind: "dynamic".to_string(), + table_kind: ManagedTableKind::Dynamic.into(), global, profile_name: if global { SHARED_PROFILE.to_string()