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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use serde::{Deserialize, Serialize};

use super::Merge;

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct CapabilityLocalityCountryV1 {
    /// Country that the placement will be applied to
    pub country: String,
    /// Sets the density of this country
    pub density: u64,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct CapabilityLocalityContinentV1 {
    /// Continent to set the density for
    pub continent: String,
    /// Sets the density of this continent
    pub density: u64,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct CapabilityLocalityCityV1 {
    /// City to set the density for
    pub city: String,
    /// Sets the density of this city
    pub density: u64,
}

/// The locality configuration allows a workload author to place
/// the workloads that respond to requests at different densities
/// in different locations.
///
/// For example, if you wanted to place a single server in the US
/// you would use this locality
///
/// ```yaml
/// locality:
///   region_density: 0
///   country_density:
///   - country: 'US'
///     density: 1
/// ```
///
/// Or perhaps you want to have the service available in most countries
/// with a decent amount of capacity except for a particular city that is blacklisted
///
/// ```yaml
/// locality:
///   region_density: 8
///   city_density:
///   - city: 'London'
///     density: 0
/// ```
///
/// The seed value allows the author to randomly move the projection of
/// where the workload runs onto a new set of servers. Simply changing
/// the seed to a different value will randomly place it somewhere different
/// than it was. This can be useful if there are noisy neighbors and you
/// want to place yourself somewhere with different neighbors
///
/// ```yaml
/// locality:
///   seed: 12345
/// ```
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, Default, schemars::JsonSchema)]
pub struct CapabilityLocalityV1 {
    /// Sets the seed for a particular placement strategy
    pub seed: Option<u64>,
    /// Represents the placement density within all the regions unless it is overridden
    /// by a country, continent or city locality
    pub region_density: Option<u64>,
    /// Sets the placement density of a particular country
    pub country_densities: Vec<CapabilityLocalityCountryV1>,
    /// Sets the placement density of a particular continent
    pub continent_densities: Vec<CapabilityLocalityContinentV1>,
    /// Sets the placement density of a particular city
    pub city_densities: Vec<CapabilityLocalityCityV1>,
}

impl Merge for CapabilityLocalityV1 {
    fn merge_extend(self, other: &Self) -> Self {
        let mut ret = Self {
            seed: self.seed,
            region_density: self.region_density.merge_extend(&other.region_density),
            country_densities: self.country_densities,
            continent_densities: self.continent_densities,
            city_densities: self.city_densities,
        };
        if let Some(seed) = other.seed {
            ret.seed = Some(seed);
        }
        ret.country_densities
            .extend(other.country_densities.clone());
        ret.continent_densities
            .extend(other.continent_densities.clone());
        ret.city_densities.extend(other.city_densities.clone());
        ret
    }
}