Skip to content

Commit e7ed972

Browse files
committed
primitive improvements:
- primitives - campaign - Pricing Bounds - primitives - sentry - Event - ad_unit and ad_slot mandatory - primitives - targeting - input - use IPFS & EventType
1 parent 830abf5 commit e7ed972

File tree

11 files changed

+216
-251
lines changed

11 files changed

+216
-251
lines changed

adview-manager/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,14 @@ pub fn get_unit_html_with_events(
211211
let event = match event_type {
212212
"CLICK" => Event::Click {
213213
publisher: options.publisher_addr,
214-
ad_unit: Some(ad_unit.id),
215-
ad_slot: Some(options.market_slot),
214+
ad_unit: ad_unit.id,
215+
ad_slot: options.market_slot,
216216
referrer: Some("document.referrer".to_string()),
217217
},
218218
_ => Event::Impression {
219219
publisher: options.publisher_addr,
220-
ad_unit: Some(ad_unit.id),
221-
ad_slot: Some(options.market_slot),
220+
ad_unit: ad_unit.id,
221+
ad_slot: options.market_slot,
222222
referrer: Some("document.referrer".to_string()),
223223
},
224224
};

primitives/src/ad_slot.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{targeting::Rule, BigNum, ValidatorId, IPFS};
1+
use crate::{targeting::Rule, ValidatorId, IPFS, Address, UnifiedNum};
22
use chrono::{
33
serde::{ts_milliseconds, ts_milliseconds_option},
44
DateTime, Utc,
@@ -25,9 +25,9 @@ pub struct AdSlot {
2525
/// see IAB ad unit guidelines and iab_flex_{adUnitName} (see IAB's new ad portfolio and PDF)
2626
#[serde(rename = "type")]
2727
pub ad_type: String,
28-
// HashMap<DepositAsset, BigNum> for the minimum payment accepted per impression
28+
// HashMap<DepositAsset, UnifiedNum> for the minimum payment accepted per impression
2929
#[serde(default)]
30-
pub min_per_impression: Option<HashMap<String, BigNum>>,
30+
pub min_per_impression: Option<HashMap<Address, UnifiedNum>>,
3131
#[serde(default)]
3232
pub rules: Vec<Rule>,
3333
/// Valid ipfs hash for Ad Unit object. It will be used as fallback data (optional)

primitives/src/campaign.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
targeting::Rules, AdUnit, Address, Channel, EventSubmission, UnifiedNum, Validator,
3-
ValidatorDesc, ValidatorId,
2+
sentry::EventType, targeting::Rules, AdUnit, Address, Channel, EventSubmission, UnifiedNum,
3+
Validator, ValidatorDesc, ValidatorId,
44
};
55

66
use chrono::{
@@ -175,10 +175,10 @@ pub struct Campaign {
175175
pub validators: Validators,
176176
#[serde(default, skip_serializing_if = "Option::is_none")]
177177
pub title: Option<String>,
178-
/// Event pricing bounds
179-
#[serde(default, skip_serializing_if = "Option::is_none")]
180-
pub pricing_bounds: Option<PricingBounds>,
181-
/// EventSubmission object, applies to event submission (POST /channel/:id/events)
178+
/// Events pricing bounds
179+
#[serde(default, skip_serializing_if = "PricingBounds::is_empty")]
180+
pub pricing_bounds: PricingBounds,
181+
/// EventSubmission object, applied to event submission
182182
#[serde(default, skip_serializing_if = "Option::is_none")]
183183
pub event_submission: Option<EventSubmission>,
184184
/// An array of AdUnit (optional)
@@ -189,7 +189,6 @@ pub struct Campaign {
189189
/// A millisecond timestamp of when the campaign was created
190190
#[serde(with = "ts_milliseconds")]
191191
pub created: DateTime<Utc>,
192-
/// A millisecond timestamp representing the time you want this campaign to become active (optional)
193192
/// Used by the AdViewManager & Targeting AIP#31
194193
#[serde(flatten, with = "prefix_active")]
195194
pub active: Active,
@@ -217,34 +216,36 @@ impl Campaign {
217216
}
218217

219218
/// Returns the pricing of a given event
220-
pub fn pricing(&self, event: &str) -> Option<&Pricing> {
221-
self.pricing_bounds
222-
.as_ref()
223-
.and_then(|bound| bound.get(event))
219+
pub fn pricing(&self, event: EventType) -> Option<&Pricing> {
220+
self.pricing_bounds.get(&event)
224221
}
225222
}
226223

227224
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
228225
pub struct Active {
226+
/// Campaign active from in a milliseconds timestamp
227+
///
228+
/// The time at which you want this campaign to become active (optional)
229229
#[serde(
230230
default,
231231
skip_serializing_if = "Option::is_none",
232232
with = "ts_milliseconds_option"
233233
)]
234234
pub from: Option<DateTime<Utc>>,
235-
//
236-
// TODO: AIP#61 Update docs
237-
//
238-
/// A millisecond timestamp of when the campaign should enter a withdraw period
239-
/// (no longer accept any events other than CHANNEL_CLOSE)
240-
/// A sane value should be lower than channel.validUntil * 1000 and higher than created
241-
/// It's recommended to set this at least one month prior to channel.validUntil * 1000
235+
/// Campaign active to in a milliseconds timestamp
236+
///
237+
/// The time at which you want this campaign to become inactive (mandatory)
242238
#[serde(with = "ts_milliseconds")]
243239
pub to: DateTime<Utc>,
244240
}
245241

246242
mod pricing {
247-
use crate::UnifiedNum;
243+
use std::{
244+
collections::HashMap,
245+
ops::{Deref, DerefMut},
246+
};
247+
248+
use crate::{sentry::EventType, UnifiedNum};
248249
use serde::{Deserialize, Serialize};
249250

250251
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
@@ -253,36 +254,33 @@ mod pricing {
253254
pub max: UnifiedNum,
254255
}
255256

256-
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
257-
#[serde(rename_all = "UPPERCASE")]
258-
pub struct PricingBounds {
259-
#[serde(default, skip_serializing_if = "Option::is_none")]
260-
pub impression: Option<Pricing>,
261-
#[serde(default, skip_serializing_if = "Option::is_none")]
262-
pub click: Option<Pricing>,
263-
}
257+
#[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
258+
#[serde(transparent)]
259+
pub struct PricingBounds(HashMap<EventType, Pricing>);
264260

265261
impl PricingBounds {
266-
pub fn to_vec(&self) -> Vec<(&str, Pricing)> {
267-
let mut vec = Vec::new();
262+
pub fn is_empty(&self) -> bool {
263+
self.0.is_empty()
264+
}
265+
}
268266

269-
if let Some(pricing) = self.impression.as_ref() {
270-
vec.push(("IMPRESSION", pricing.clone()));
271-
}
267+
impl FromIterator<(EventType, Pricing)> for PricingBounds {
268+
fn from_iter<T: IntoIterator<Item = (EventType, Pricing)>>(iter: T) -> Self {
269+
Self(iter.into_iter().collect())
270+
}
271+
}
272272

273-
if let Some(pricing) = self.click.as_ref() {
274-
vec.push(("CLICK", pricing.clone()))
275-
}
273+
impl Deref for PricingBounds {
274+
type Target = HashMap<EventType, Pricing>;
276275

277-
vec
276+
fn deref(&self) -> &Self::Target {
277+
&self.0
278278
}
279+
}
279280

280-
pub fn get(&self, event_type: &str) -> Option<&Pricing> {
281-
match event_type {
282-
"IMPRESSION" => self.impression.as_ref(),
283-
"CLICK" => self.click.as_ref(),
284-
_ => None,
285-
}
281+
impl DerefMut for PricingBounds {
282+
fn deref_mut(&mut self) -> &mut Self::Target {
283+
&mut self.0
286284
}
287285
}
288286
}

primitives/src/sentry.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ mod event {
187187
#[serde(rename_all = "camelCase")]
188188
Impression {
189189
publisher: Address,
190-
ad_unit: Option<IPFS>,
191-
ad_slot: Option<IPFS>,
190+
ad_unit: IPFS,
191+
ad_slot: IPFS,
192192
referrer: Option<String>,
193193
},
194194
#[serde(rename_all = "camelCase")]
195195
Click {
196196
publisher: Address,
197-
ad_unit: Option<IPFS>,
198-
ad_slot: Option<IPFS>,
197+
ad_unit: IPFS,
198+
ad_slot: IPFS,
199199
referrer: Option<String>,
200200
},
201201
}
@@ -276,8 +276,8 @@ mod event {
276276
pub struct UpdateAnalytics {
277277
pub time: DateHour<Utc>,
278278
pub campaign_id: CampaignId,
279-
pub ad_unit: Option<IPFS>,
280-
pub ad_slot: Option<IPFS>,
279+
pub ad_unit: IPFS,
280+
pub ad_slot: IPFS,
281281
pub ad_slot_type: Option<String>,
282282
pub advertiser: Address,
283283
pub publisher: Address,
@@ -294,8 +294,8 @@ pub struct UpdateAnalytics {
294294
pub struct Analytics {
295295
pub time: DateHour<Utc>,
296296
pub campaign_id: CampaignId,
297-
pub ad_unit: Option<IPFS>,
298-
pub ad_slot: Option<IPFS>,
297+
pub ad_unit: IPFS,
298+
pub ad_slot: IPFS,
299299
pub ad_slot_type: Option<String>,
300300
pub advertiser: Address,
301301
pub publisher: Address,
@@ -780,8 +780,8 @@ pub mod campaign_create {
780780
#[serde(default, skip_serializing_if = "Option::is_none")]
781781
pub title: Option<String>,
782782
/// Event pricing bounds
783-
#[serde(default, skip_serializing_if = "Option::is_none")]
784-
pub pricing_bounds: Option<PricingBounds>,
783+
#[serde(default, skip_serializing_if = "PricingBounds::is_empty")]
784+
pub pricing_bounds: PricingBounds,
785785
/// EventSubmission object, applies to event submission (POST /channel/:id/events)
786786
#[serde(default, skip_serializing_if = "Option::is_none")]
787787
pub event_submission: Option<EventSubmission>,
@@ -874,7 +874,7 @@ pub mod campaign_modify {
874874
budget: Some(campaign.budget),
875875
validators: Some(campaign.validators),
876876
title: campaign.title,
877-
pricing_bounds: campaign.pricing_bounds,
877+
pricing_bounds: Some(campaign.pricing_bounds),
878878
event_submission: campaign.event_submission,
879879
ad_units: Some(campaign.ad_units),
880880
targeting_rules: Some(campaign.targeting_rules),
@@ -896,7 +896,7 @@ pub mod campaign_modify {
896896
}
897897

898898
if let Some(new_pricing_bounds) = self.pricing_bounds {
899-
campaign.pricing_bounds = Some(new_pricing_bounds);
899+
campaign.pricing_bounds = new_pricing_bounds;
900900
}
901901

902902
if let Some(new_event_submission) = self.event_submission {
@@ -924,7 +924,7 @@ mod postgres {
924924
};
925925
use crate::{
926926
analytics::{AnalyticsQuery, Metric},
927-
validator::{messages::Type as MessageType, MessageTypes},
927+
validator::{messages::Type as MessageType, MessageTypes}, IPFS,
928928
};
929929
use bytes::BytesMut;
930930
use chrono::{DateTime, Timelike, Utc};
@@ -989,20 +989,8 @@ mod postgres {
989989
.get::<_, Option<String>>("country")
990990
.filter(|string| !string.is_empty());
991991

992-
let ad_unit = row.get::<_, Option<String>>("ad_unit").and_then(|string| {
993-
if !string.is_empty() {
994-
Some(string.parse().expect("Valid IPFS"))
995-
} else {
996-
None
997-
}
998-
});
999-
let ad_slot = row.get::<_, Option<String>>("ad_slot").and_then(|string| {
1000-
if !string.is_empty() {
1001-
Some(string.parse().expect("Valid IPFS"))
1002-
} else {
1003-
None
1004-
}
1005-
});
992+
let ad_unit = row.get::<_, IPFS>("ad_unit");
993+
let ad_slot = row.get::<_, IPFS>("ad_slot");
1006994

1007995
Self {
1008996
campaign_id: row.get("campaign_id"),
@@ -1122,8 +1110,8 @@ mod test {
11221110
pub fn test_de_serialize_events() {
11231111
let click = Event::Click {
11241112
publisher: *PUBLISHER,
1125-
ad_unit: Some(DUMMY_IPFS[0]),
1126-
ad_slot: Some(DUMMY_IPFS[1]),
1113+
ad_unit: DUMMY_IPFS[0],
1114+
ad_slot: DUMMY_IPFS[1],
11271115
referrer: Some("some_referrer".to_string()),
11281116
};
11291117

primitives/src/targeting.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{campaign::Pricing, Campaign, UnifiedNum};
1+
use crate::{campaign::Pricing, sentry::EventType, Campaign, UnifiedNum};
22

33
pub use eval::*;
44
use serde_json::Number;
@@ -9,11 +9,10 @@ pub use input::{field::GetField, Input};
99
mod eval;
1010
pub mod input;
1111

12-
pub fn get_pricing_bounds(campaign: &Campaign, event_type: &str) -> Pricing {
12+
pub fn get_pricing_bounds(campaign: &Campaign, event_type: &EventType) -> Pricing {
1313
campaign
1414
.pricing_bounds
15-
.as_ref()
16-
.and_then(|pricing_bounds| pricing_bounds.get(event_type))
15+
.get(event_type)
1716
.cloned()
1817
.unwrap_or_else(|| Pricing {
1918
min: 0.into(),
@@ -59,14 +58,11 @@ impl Output {
5958

6059
impl From<&Campaign> for Output {
6160
fn from(campaign: &Campaign) -> Self {
62-
let price = match &campaign.pricing_bounds {
63-
Some(pricing_bounds) => pricing_bounds
64-
.to_vec()
65-
.into_iter()
66-
.map(|(key, price)| (key.to_string(), price.min))
67-
.collect(),
68-
_ => Default::default(),
69-
};
61+
let price = campaign
62+
.pricing_bounds
63+
.iter()
64+
.map(|(key, price)| (key.to_string(), price.min))
65+
.collect();
7066

7167
Self {
7268
show: true,
@@ -78,6 +74,8 @@ impl From<&Campaign> for Output {
7874

7975
#[cfg(test)]
8076
mod test {
77+
use crate::sentry::{CLICK, IMPRESSION};
78+
8179
use super::*;
8280

8381
#[test]
@@ -106,20 +104,28 @@ mod test {
106104
#[test]
107105
#[allow(clippy::float_cmp)]
108106
fn test_output_from_channel() {
109-
use crate::campaign::{Pricing, PricingBounds};
107+
use crate::campaign::Pricing;
110108
use crate::test_util::DUMMY_CAMPAIGN;
111109

112110
let mut campaign = DUMMY_CAMPAIGN.clone();
113-
campaign.pricing_bounds = Some(PricingBounds {
114-
impression: Some(Pricing {
115-
min: 1_000.into(),
116-
max: 2_000.into(),
117-
}),
118-
click: Some(Pricing {
119-
min: 3_000.into(),
120-
max: 4_000.into(),
121-
}),
122-
});
111+
campaign.pricing_bounds = vec![
112+
(
113+
IMPRESSION,
114+
Pricing {
115+
min: 1_000.into(),
116+
max: 2_000.into(),
117+
},
118+
),
119+
(
120+
CLICK,
121+
Pricing {
122+
min: 3_000.into(),
123+
max: 4_000.into(),
124+
},
125+
),
126+
]
127+
.into_iter()
128+
.collect();
123129

124130
let output = Output::from(&campaign);
125131

0 commit comments

Comments
 (0)