@@ -23,7 +23,6 @@ use arrow::{
2323} ;
2424use arrow_array:: { ArrayRef , RecordBatch , UInt32Array } ;
2525use arrow_schema:: { ArrowError , Field , Fields , Schema , SortOptions } ;
26- use bytes:: Bytes ;
2726use chrono:: { NaiveDate , NaiveDateTime , Timelike , Utc } ;
2827use derive_more:: derive:: { Deref , DerefMut } ;
2928use itertools:: Itertools ;
@@ -52,7 +51,8 @@ use rayon::{
5251 slice:: ParallelSliceMut ,
5352} ;
5453use relative_path:: RelativePathBuf ;
55- use std:: sync:: PoisonError ;
54+ use rustc_hash:: FxHasher ;
55+ use serde:: { Deserialize , Serialize } ;
5656use std:: {
5757 collections:: { HashMap , HashSet , VecDeque } ,
5858 fs:: { self , File , OpenOptions , remove_file, write} ,
@@ -62,6 +62,10 @@ use std::{
6262 sync:: { Arc , Mutex , RwLock } ,
6363 time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ,
6464} ;
65+ use std:: {
66+ hash:: { Hash , Hasher } ,
67+ sync:: PoisonError ,
68+ } ;
6569use tokio:: task:: JoinSet ;
6670use tracing:: { error, info, info_span, instrument, trace, warn} ;
6771use ulid:: Ulid ;
@@ -80,7 +84,7 @@ use crate::{
8084 option:: Mode ,
8185 parseable:: { DEFAULT_TENANT , PARSEABLE } ,
8286 schema_registry:: Resolution ,
83- storage:: { StreamType , object_storage:: to_bytes, retention:: Retention } ,
87+ storage:: { ComparableBytes , StreamType , object_storage:: to_bytes, retention:: Retention } ,
8488 sync:: FLUSH_AND_CONVERT_RUNTIME ,
8589 utils:: {
8690 arrow:: adapt_batch,
@@ -374,15 +378,24 @@ fn minute_from_system_time(time: SystemTime) -> u128 {
374378 / 60000
375379}
376380
377- #[ derive( Debug , Clone ) ]
381+ #[ derive( Debug , Clone , Deserialize , Serialize ) ]
378382pub struct GlobalSchema {
379- pub schema : Bytes ,
380- pub version : object_store :: UpdateVersion ,
383+ pub schema : Schema ,
384+ pub hash : u64 ,
381385}
382386
383387impl GlobalSchema {
384- pub fn new ( schema : Bytes , version : object_store:: UpdateVersion ) -> Self {
385- Self { schema, version }
388+ pub fn from_schema ( schema : Schema ) -> Self {
389+ let mut hasher = FxHasher :: with_seed ( 0 ) ;
390+ schema. hash ( & mut hasher) ;
391+ let hash = hasher. finish ( ) ;
392+ Self { schema, hash }
393+ }
394+ }
395+
396+ impl ComparableBytes for GlobalSchema {
397+ fn get_hash ( & self ) -> u64 {
398+ self . hash
386399 }
387400}
388401
@@ -1179,7 +1192,7 @@ impl Stream {
11791192 {
11801193 // The registry is authoritative. Raw schemas staged before the
11811194 // first coordinated conversion may contain the losing field type.
1182- schema = global. as_ref ( ) . clone ( ) ;
1195+ schema = global. as_ref ( ) . to_owned ( ) ;
11831196 } else {
11841197 let staging_schemas = self . get_schemas_if_present ( ) ?;
11851198 if !staging_schemas. is_empty ( ) {
@@ -1876,12 +1889,11 @@ impl Stream {
18761889 }
18771890
18781891 fn can_use_global_schema ( & self ) -> bool {
1879- self . options . mode == Mode :: Ingest
1880- && !self . get_static_schema_flag ( )
1881- && PARSEABLE
1882- . storage
1883- . get_object_store ( )
1884- . supports_conditional_writes ( )
1892+ self . options . mode == Mode :: Ingest && !self . get_static_schema_flag ( )
1893+ // && PARSEABLE
1894+ // .storage
1895+ // .get_object_store()
1896+ // .supports_conditional_writes()
18851897 }
18861898
18871899 fn uses_global_schema ( & self ) -> bool {
@@ -1973,7 +1985,7 @@ impl Stream {
19731985 "global schema disappeared after resolution" . to_owned ( ) ,
19741986 )
19751987 } ) ?;
1976- let canonical = serde_json :: from_slice :: < Schema > ( & global. schema ) ? ;
1988+ let canonical = global. schema ;
19771989 Ok :: < _ , StagingError > ( ( resolution, Arc :: new ( canonical) ) )
19781990 } ) ?;
19791991 resolution. include_identity_schema ( & canonical) ;
@@ -2146,6 +2158,7 @@ impl Stream {
21462158
21472159 /// Converts one Parquet output group and removes its Arrow sources only
21482160 /// after the final Parquet rename succeeds.
2161+ #[ allow( clippy:: too_many_arguments) ]
21492162 fn convert_arrow_group (
21502163 & self ,
21512164 parquet_path : PathBuf ,
@@ -2225,6 +2238,7 @@ impl Stream {
22252238
22262239 #[ cfg_attr( feature = "hotpath" , hotpath:: measure) ]
22272240 /// Writes one conversion group to a temporary Parquet file.
2241+ #[ allow( clippy:: too_many_arguments) ]
22282242 fn write_parquet_part_file (
22292243 & self ,
22302244 part_path : & Path ,
@@ -2287,6 +2301,7 @@ impl Stream {
22872301
22882302 /// Writes a metric conversion group with pipelined row-group preparation
22892303 /// and encoding while preserving row-group output order.
2304+ #[ allow( clippy:: too_many_arguments) ]
22902305 fn write_metric_parquet_part_file (
22912306 & self ,
22922307 part_path : & Path ,
@@ -2632,7 +2647,7 @@ impl Stream {
26322647 . ok_or_else ( || {
26332648 StagingError :: GlobalSchema ( "global schema disappeared during startup" . to_owned ( ) )
26342649 } ) ?;
2635- let canonical = serde_json :: from_slice :: < Schema > ( & global. schema ) ? ;
2650+ let canonical = global. schema ;
26362651 resolution. include_identity_schema ( & canonical) ;
26372652 * self . global_schema . write ( ) . expect ( LOCK_EXPECT ) =
26382653 Some ( ( Arc :: new ( canonical. clone ( ) ) , Arc :: new ( resolution) ) ) ;
0 commit comments