mirror of https://github.com/buster-so/buster.git
added version history
This commit is contained in:
parent
70121cc629
commit
e9fc5cf9bb
|
@ -5,10 +5,11 @@ use database::{
|
|||
models::{DashboardFile, MetricFile},
|
||||
pool::get_pg_pool,
|
||||
schema::{datasets, metric_files},
|
||||
types::VersionHistory,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use query_engine::{data_source_query_routes::query_engine::query_engine, data_types::DataType};
|
||||
use serde_json;
|
||||
use serde_json::{self};
|
||||
use serde_yaml;
|
||||
use tracing::{debug, error};
|
||||
use uuid::Uuid;
|
||||
|
@ -589,12 +590,16 @@ pub async fn process_metric_file(
|
|||
Err(e) => return Err(format!("Invalid SQL query: {}", e)),
|
||||
};
|
||||
|
||||
let metric_yml_json = match serde_json::to_value(metric_yml.clone()) {
|
||||
Ok(json) => json,
|
||||
Err(e) => return Err(format!("Failed to process metric: {}", e)),
|
||||
};
|
||||
|
||||
let metric_file = MetricFile {
|
||||
id: metric_id,
|
||||
name: file_name.clone(),
|
||||
file_name: file_name.clone(),
|
||||
content: serde_json::to_value(metric_yml.clone())
|
||||
.map_err(|e| format!("Failed to process metric: {}", e))?,
|
||||
content: metric_yml_json.clone(),
|
||||
created_by: Uuid::new_v4(),
|
||||
verification: Verification::NotRequested,
|
||||
evaluation_obj: None,
|
||||
|
@ -607,6 +612,7 @@ pub async fn process_metric_file(
|
|||
publicly_accessible: false,
|
||||
publicly_enabled_by: None,
|
||||
public_expiry_date: None,
|
||||
version_history: VersionHistory::new(1, metric_yml_json),
|
||||
};
|
||||
|
||||
Ok((metric_file, metric_yml, message, results))
|
||||
|
|
|
@ -4,11 +4,11 @@ use std::time::Instant;
|
|||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::Utc;
|
||||
use database::{models::DashboardFile, pool::get_pg_pool, schema::dashboard_files};
|
||||
use database::{models::DashboardFile, pool::get_pg_pool, schema::dashboard_files, types::VersionHistory};
|
||||
use diesel::insert_into;
|
||||
use diesel_async::RunQueryDsl;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use serde_json::{self, json, Value};
|
||||
use tracing::debug;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -19,10 +19,7 @@ use crate::{
|
|||
|
||||
use super::{
|
||||
common::{generate_deterministic_uuid, validate_metric_ids},
|
||||
file_types::{
|
||||
dashboard_yml::DashboardYml,
|
||||
file::{FileWithId},
|
||||
},
|
||||
file_types::{dashboard_yml::DashboardYml, file::FileWithId},
|
||||
FileModificationTool,
|
||||
};
|
||||
|
||||
|
@ -95,12 +92,16 @@ async fn process_dashboard_file(
|
|||
}
|
||||
}
|
||||
|
||||
let dashboard_yml_json = match serde_json::to_value(dashboard_yml.clone()) {
|
||||
Ok(json) => json,
|
||||
Err(e) => return Err(format!("Failed to process dashboard: {}", e)),
|
||||
};
|
||||
|
||||
let dashboard_file = DashboardFile {
|
||||
id: dashboard_id,
|
||||
name: dashboard_yml.name.clone(),
|
||||
file_name: file.name.clone(),
|
||||
content: serde_json::to_value(dashboard_yml.clone())
|
||||
.map_err(|e| format!("Failed to process dashboard: {}", e))?,
|
||||
content: dashboard_yml_json.clone(),
|
||||
filter: None,
|
||||
organization_id: Uuid::new_v4(),
|
||||
created_by: Uuid::new_v4(),
|
||||
|
@ -110,6 +111,7 @@ async fn process_dashboard_file(
|
|||
publicly_accessible: false,
|
||||
publicly_enabled_by: None,
|
||||
public_expiry_date: None,
|
||||
version_history: VersionHistory::new(1, dashboard_yml_json),
|
||||
};
|
||||
|
||||
Ok((dashboard_file, dashboard_yml))
|
||||
|
|
|
@ -4,5 +4,6 @@ pub mod models;
|
|||
pub mod schema;
|
||||
pub mod vault;
|
||||
pub mod helpers;
|
||||
pub mod types;
|
||||
|
||||
pub use helpers::*;
|
|
@ -5,6 +5,7 @@ use diesel::prelude::*;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use uuid::Uuid;
|
||||
use crate::types::VersionHistory;
|
||||
|
||||
#[derive(Queryable, Insertable, Identifiable, Associations, Debug)]
|
||||
#[diesel(belongs_to(User, foreign_key = owner_id))]
|
||||
|
@ -35,6 +36,7 @@ pub struct DashboardFile {
|
|||
pub publicly_accessible: bool,
|
||||
pub publicly_enabled_by: Option<Uuid>,
|
||||
pub public_expiry_date: Option<DateTime<Utc>>,
|
||||
pub version_history: VersionHistory,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, Identifiable, Associations, Debug, Clone, Serialize)]
|
||||
|
@ -85,6 +87,7 @@ pub struct MetricFile {
|
|||
pub publicly_accessible: bool,
|
||||
pub publicly_enabled_by: Option<Uuid>,
|
||||
pub public_expiry_date: Option<DateTime<Utc>>,
|
||||
pub version_history: VersionHistory,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, Identifiable, Associations, Debug, Clone, Serialize)]
|
||||
|
|
|
@ -143,6 +143,7 @@ diesel::table! {
|
|||
publicly_accessible -> Bool,
|
||||
publicly_enabled_by -> Nullable<Uuid>,
|
||||
public_expiry_date -> Nullable<Timestamptz>,
|
||||
version_history -> Jsonb,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,6 +400,7 @@ diesel::table! {
|
|||
publicly_accessible -> Bool,
|
||||
publicly_enabled_by -> Nullable<Uuid>,
|
||||
public_expiry_date -> Nullable<Timestamptz>,
|
||||
version_history -> Jsonb,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
use std::io::Write;
|
||||
|
||||
use diesel::{
|
||||
deserialize::FromSql,
|
||||
pg::Pg,
|
||||
serialize::{IsNull, Output, ToSql},
|
||||
sql_types::Jsonb,
|
||||
AsExpression, FromSqlRow,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, FromSqlRow, AsExpression, Clone)]
|
||||
#[diesel(sql_type = Jsonb)]
|
||||
#[serde(transparent)]
|
||||
pub struct VersionHistory(pub std::collections::HashMap<String, Version>);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Version {
|
||||
pub version_number: i32,
|
||||
pub content: Value,
|
||||
}
|
||||
|
||||
impl VersionHistory {
|
||||
pub fn new(version_number: i32, content: Value) -> Self {
|
||||
Self(std::collections::HashMap::from([(
|
||||
version_number.to_string(),
|
||||
Version {
|
||||
content,
|
||||
version_number,
|
||||
},
|
||||
)]))
|
||||
}
|
||||
|
||||
pub fn add_version(&mut self, version_number: i32, content: Value) {
|
||||
self.0.insert(
|
||||
version_number.to_string(),
|
||||
Version {
|
||||
content,
|
||||
version_number,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_version(&self, version_number: i32) -> Option<&Version> {
|
||||
self.0.get(&version_number.to_string())
|
||||
}
|
||||
|
||||
pub fn get_latest_version(&self) -> Option<&Version> {
|
||||
self.0.values().max_by_key(|v| v.version_number)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<Jsonb, Pg> for VersionHistory {
|
||||
fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as FromSql<Jsonb, Pg>>::from_sql(bytes)?;
|
||||
Ok(serde_json::from_value(value)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql<Jsonb, Pg> for VersionHistory {
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> diesel::serialize::Result {
|
||||
out.write_all(&[1])?; // JSONB version 1 header
|
||||
out.write_all(&serde_json::to_vec(self)?)?;
|
||||
Ok(IsNull::No)
|
||||
}
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use diesel::{
|
||||
ExpressionMethods, NullableExpressionMethods, QueryDsl, Queryable, Selectable, SelectableHelper,
|
||||
};
|
||||
use database::types::VersionHistory;
|
||||
use diesel::{ExpressionMethods, QueryDsl, Queryable, Selectable, SelectableHelper};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use serde_json::{json, Value};
|
||||
use serde_json::Value;
|
||||
use serde_yaml;
|
||||
use uuid::Uuid;
|
||||
use middleware::AuthenticatedUser;
|
||||
|
||||
use crate::metrics::types::{
|
||||
BusterMetric, ColumnMetaData, ColumnType, DataMetadata, Dataset, MinMaxValue, SimpleType,
|
||||
|
@ -14,7 +12,7 @@ use crate::metrics::types::{
|
|||
use agents::tools::file_tools::file_types::metric_yml::MetricYml;
|
||||
use database::enums::Verification;
|
||||
use database::pool::get_pg_pool;
|
||||
use database::schema::{datasets, metric_files, users};
|
||||
use database::schema::{datasets, metric_files};
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = metric_files)]
|
||||
|
@ -30,6 +28,7 @@ struct QueryableMetricFile {
|
|||
created_by: Uuid,
|
||||
created_at: chrono::DateTime<chrono::Utc>,
|
||||
updated_at: chrono::DateTime<chrono::Utc>,
|
||||
version_history: VersionHistory,
|
||||
}
|
||||
|
||||
#[derive(Queryable)]
|
||||
|
@ -70,6 +69,7 @@ pub async fn get_metric_handler(metric_id: &Uuid, user_id: &Uuid) -> Result<Bust
|
|||
metric_files::created_by,
|
||||
metric_files::created_at,
|
||||
metric_files::updated_at,
|
||||
metric_files::version_history,
|
||||
))
|
||||
.first::<QueryableMetricFile>(&mut conn)
|
||||
.await
|
||||
|
@ -180,5 +180,6 @@ pub async fn get_metric_handler(metric_id: &Uuid, user_id: &Uuid) -> Result<Bust
|
|||
code: None,
|
||||
dashboards: vec![], // TODO: Get associated dashboards
|
||||
collections: vec![], // TODO: Get associated collections
|
||||
versions: metric_file.version_history,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use database::enums::Verification;
|
||||
use database::{enums::Verification, types::VersionHistory};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
@ -9,6 +9,12 @@ pub struct Dataset {
|
|||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Version {
|
||||
pub version_number: i32,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BusterMetric {
|
||||
pub id: String,
|
||||
|
@ -36,6 +42,7 @@ pub struct BusterMetric {
|
|||
pub code: Option<String>,
|
||||
pub dashboards: Vec<Dashboard>,
|
||||
pub collections: Vec<Collection>,
|
||||
pub versions: VersionHistory,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
@ -133,4 +140,4 @@ pub enum DataValue {
|
|||
String(String),
|
||||
Number(f64),
|
||||
Null,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,3 +26,11 @@ ALTER TABLE dashboard_files
|
|||
ADD COLUMN publicly_accessible boolean NOT NULL DEFAULT false,
|
||||
ADD COLUMN publicly_enabled_by uuid NULL REFERENCES users(id),
|
||||
ADD COLUMN public_expiry_date timestamp with time zone NULL;
|
||||
|
||||
-- Add version_history column to metric_files table
|
||||
ALTER TABLE metric_files
|
||||
ADD COLUMN version_history JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
|
||||
-- Add version_history column to dashboard_files table
|
||||
ALTER TABLE dashboard_files
|
||||
ADD COLUMN version_history JSONB NOT NULL DEFAULT '{}'::jsonb;
|
Loading…
Reference in New Issue