1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use std::marker::PhantomData;

use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use tantivy::SegmentAttributesMerger;

use crate::utils::current_time;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SummaSegmentAttributes {
    pub is_frozen: bool,
    pub created_at: Option<u64>,
}

impl Default for SummaSegmentAttributes {
    fn default() -> Self {
        SummaSegmentAttributes {
            is_frozen: false,
            created_at: Some(current_time()),
        }
    }
}

impl SummaSegmentAttributes {
    pub fn frozen() -> Self {
        SummaSegmentAttributes {
            is_frozen: true,
            created_at: Some(current_time()),
        }
    }
}

/// SegmentAttributes implementation owns custom segment attributes and its merging behavior
pub trait SegmentAttributes: Default + Serialize + DeserializeOwned + Send + Sync + Clone {
    /// Must be implemented for defining how to merge `SegmentAttributes` from
    /// different segments
    fn merge(segments_attributes: Vec<Self>) -> Self;
}

#[derive(Clone)]
pub struct SegmentAttributesMergerImpl<S: SegmentAttributes> {
    _phantom: PhantomData<S>,
}

impl<S: SegmentAttributes> SegmentAttributesMergerImpl<S> {
    pub fn new() -> SegmentAttributesMergerImpl<S> {
        SegmentAttributesMergerImpl { _phantom: PhantomData }
    }
}

impl<S: SegmentAttributes + 'static> SegmentAttributesMerger for SegmentAttributesMergerImpl<S> {
    fn merge_json(&self, segment_attributes_json: Vec<&serde_json::Value>) -> serde_json::Value {
        let segment_attributes: Vec<_> = segment_attributes_json.into_iter().flat_map(|v| serde_json::from_value(v.clone())).collect();
        serde_json::to_value(S::merge(segment_attributes)).expect("not serializable")
    }

    fn default(&self) -> serde_json::Value {
        serde_json::to_value(S::default()).expect("not serializable")
    }
}

impl SegmentAttributes for SummaSegmentAttributes {
    fn merge(segments_attributes: Vec<Self>) -> Self {
        SummaSegmentAttributes {
            is_frozen: segments_attributes.into_iter().map(|v| v.is_frozen).reduce(|a, b| a && b).unwrap_or(false),
            created_at: Some(current_time()),
        }
    }
}