Skip to content

Commit 9ff588a

Browse files
committed
sentry - Improve docs & create InsertEventsRequest
1 parent 79e4990 commit 9ff588a

File tree

7 files changed

+90
-37
lines changed

7 files changed

+90
-37
lines changed

primitives/Cargo.toml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ postgres = ["bytes", "tokio-postgres", "deadpool-postgres"]
2121
test-util = []
2222

2323
[[example]]
24-
name = "channel_list_query"
25-
required-features = ["test-util"]
24+
name = "analytics_query"
25+
26+
[[example]]
27+
name = "analytics_response"
2628

2729
[[example]]
2830
name = "campaign_list_query"
@@ -32,10 +34,17 @@ required-features = ["test-util"]
3234
name = "campaign_list_response"
3335
required-features = ["test-util"]
3436

37+
[[example]]
38+
name = "channel_list_query"
39+
required-features = ["test-util"]
40+
3541
[[example]]
3642
name = "create_campaign"
3743
required-features = ["test-util"]
3844

45+
[[example]]
46+
name = "modify_campaign"
47+
3948
[dependencies]
4049
# (De)Serialization
4150
serde = { version = "1.0", features = ["derive"] }

primitives/examples/analytics_query.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,16 @@ fn main() {
4141

4242
// Query with all possible fields (publisher/advertiser/admin)
4343
{
44-
let query_str = "limit=200&eventType=CLICK&metric=paid&segmentBy=country&timeframe=week&start=2022-08-04+09:00:00.000000000+UTC&campaignId=0x936da01f9abd4d9d80c702af85c822a8&adUnit=QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR&adSlot=Qmasg8FrbuSQpjFu3kRnZF9beg8rEBFrqgi1uXDRwCbX5f&adSlotType=legacy_300x100&advertiser=0xDd589B43793934EF6Ad266067A0d1D4896b0dff0&publisher=0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9\
45-
&hostname=localhost&country=Bulgaria&osName=Windows&chains[0]=1&chains[1]=1337";
44+
let query_str = "limit=200&eventType=CLICK&metric=paid&segmentBy=country\
45+
&timeframe=week&start=2022-08-04+09:00:00.000000000+UTC\
46+
&campaignId=0x936da01f9abd4d9d80c702af85c822a8\
47+
&adUnit=QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR\
48+
&adSlot=Qmasg8FrbuSQpjFu3kRnZF9beg8rEBFrqgi1uXDRwCbX5f\
49+
&adSlotType=legacy_300x100\
50+
&advertiser=0xDd589B43793934EF6Ad266067A0d1D4896b0dff0\
51+
&publisher=0xE882ebF439207a70dDcCb39E13CA8506c9F45fD9\
52+
&hostname=localhost&country=Bulgaria&osName=Windows\
53+
&chains[0]=1&chains[1]=1337";
4654
let query: AnalyticsQuery = serde_qs::from_str(query_str).unwrap();
4755

4856
assert_eq!(query.limit, 200);

primitives/examples/create_campaign.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ use serde_json::json;
33
use std::str::FromStr;
44

55
fn main() {
6-
// CreateCampaign in an HTTP request
6+
// CreateCampaign in an HTTP request.
7+
// A CampaignId will be randomly generated for the newly created Campaign.
78
{
89
let create_campaign = CreateCampaign::from_campaign_erased(DUMMY_CAMPAIGN.clone(), None);
910

10-
let create_campaign_str =
11+
let _create_campaign_str =
1112
serde_json::to_string(&create_campaign).expect("should serialize");
1213

1314
let create_campaign_json = json!({
14-
"id":null,
1515
"channel":{
1616
"leader":"0x80690751969B234697e9059e04ed72195c3507fa",
1717
"follower":"0xf3f583AEC5f7C030722Fe992A5688557e1B86ef7",
@@ -34,7 +34,10 @@ fn main() {
3434
}
3535
],
3636
"title":"Dummy Campaign",
37-
"pricingBounds":{"CLICK":{"min":"0","max":"0"},"IMPRESSION":{"min":"1","max":"10"}},
37+
"pricingBounds":{
38+
"CLICK":{"min":"0","max":"0"},
39+
"IMPRESSION":{"min":"1","max":"10"}
40+
},
3841
"eventSubmission":{"allow":[]},
3942
"targetingRules":[],
4043
"created":1612162800000_u64,
@@ -43,6 +46,7 @@ fn main() {
4346

4447
let create_campaign_json =
4548
serde_json::to_string(&create_campaign_json).expect("should serialize");
49+
4650
let deserialized: CreateCampaign =
4751
serde_json::from_str(&create_campaign_json).expect("should deserialize");
4852

primitives/examples/modify_campaign.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use primitives::{sentry::campaign_modify::ModifyCampaign, unified_num::FromWhole, UnifiedNum};
22
use serde_json::json;
3-
use std::str::FromStr;
43

54
fn main() {
65
{

primitives/src/sentry.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,10 @@ pub struct FetchedAnalytics {
319319
pub segment: Option<String>,
320320
}
321321

322-
// Response returned when getting Analytics - an array of FetchedAnalytics
323-
//
324-
/// # Examples:
322+
/// Response returned when getting Analytics which returns the [`FetchedAnalytics`].
323+
///
324+
/// # Examples
325+
///
325326
/// ```
326327
#[doc = include_str!("../examples/analytics_response.rs")]
327328
/// ```
@@ -651,6 +652,13 @@ pub struct ValidationErrorResponse {
651652
pub validation: Vec<String>,
652653
}
653654

655+
/// Request body for posting new [`Event`]s to a [`Campaign`](crate::Campaign).
656+
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
657+
#[serde(rename_all = "camelCase")]
658+
pub struct InsertEventsRequest {
659+
pub events: Vec<Event>,
660+
}
661+
654662
pub mod channel_list {
655663
use crate::{ChainId, Channel, ValidatorId};
656664
use serde::{Deserialize, Serialize};

sentry/src/routes.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@
106106
//!
107107
//! Request body (json): [`ValidatorMessagesCreateRequest`](primitives::sentry::ValidatorMessagesCreateRequest)
108108
//!
109-
//! Example:
109+
//! ##### Examples:
110+
//!
110111
//! ```json
111112
//! {
112113
//! "messages": [
@@ -231,14 +232,20 @@
231232
//! **Authentication is required** to validate [`Campaign.creator`](primitives::Campaign::creator) == [`Auth.uid`](crate::Auth::uid)
232233
//!
233234
//! It will make sure the `Channel` is created if new and it will update
234-
//! the spendable amount using the [`Adapter`]`::get_deposit()`.
235+
//! the spendable amount using the [`Adapter.get_deposit()`](adapter::client::Locked::get_deposit).
235236
//!
236237
//! The route is handled by [`campaign::create_campaign()`].
237238
//!
238239
//! Request body (json): [`CreateCampaign`][primitives::sentry::campaign_create::CreateCampaign]
239240
//!
240241
//! Response: [`Campaign`]
241242
//!
243+
//! ##### Examples
244+
//!
245+
//! ```
246+
#![doc = include_str!("../../primitives/examples/create_campaign.rs")]
247+
//! ```
248+
//!
242249
//! #### POST `/v5/campaign/:id` (auth required)
243250
//!
244251
//! Modify the [`Campaign`]. Request must be sent by the [`Campaign.creator`](primitives::Campaign::creator).
@@ -251,22 +258,20 @@
251258
//!
252259
//! Response: [`Campaign`]
253260
//!
261+
//! ##### Examples
262+
//!
263+
//! ```
264+
#![doc = include_str!("../../primitives/examples/modify_campaign.rs")]
265+
//! ```
266+
//!
254267
//! #### POST `/v5/campaign/:id/events`
255268
//!
256269
//! Add new [`Event`]s (`IMPRESSION`s & `CLICK`s) to the [`Campaign`].
257270
//! Applies [`Campaign.event_submission`] rules and additional validation using [`check_access()`].
258271
//!
259272
//! The route is handled by [`campaign::insert_events::handle_route()`].
260273
//!
261-
//! Request body (json):
262-
//!
263-
//! ```json
264-
//! {
265-
//! "events": [
266-
//! // Events
267-
//! ]
268-
//! }
269-
//! ```
274+
//! Request body (json): [`InsertEventsRequest`](primitives::sentry::InsertEventsRequest)
270275
//!
271276
//! Response: [`SuccessResponse`]
272277
//!
@@ -294,6 +299,20 @@
294299
//!
295300
//! Response: [`AnalyticsResponse`]
296301
//!
302+
//! ##### Examples
303+
//!
304+
//! Query:
305+
//!
306+
//! ```
307+
#![doc = include_str!("../../primitives/examples/analytics_query.rs")]
308+
//! ```
309+
//!
310+
//! Response:
311+
//!
312+
//! ```
313+
#![doc = include_str!("../../primitives/examples/analytics_response.rs")]
314+
//! ```
315+
//!
297316
//! #### GET `/v5/analytics/for-publisher` (auth required)
298317
//!
299318
//! Returns all analytics where the currently authenticated address [`Auth.uid`](crate::Auth::uid) is a **publisher**.
@@ -306,6 +325,10 @@
306325
//!
307326
//! Response: [`AnalyticsResponse`]
308327
//!
328+
//! ##### Examples
329+
//!
330+
//! See [GET `/v5/analytics`](#get-v5analytics)
331+
//!
309332
//! #### GET `/v5/analytics/for-advertiser` (auth required)
310333
//!
311334
//! Returns all analytics where the currently authenticated address [`Auth.uid`](crate::Auth::uid) is an **advertiser**.
@@ -318,6 +341,10 @@
318341
//!
319342
//! Response: [`AnalyticsResponse`]
320343
//!
344+
//! ##### Examples
345+
//!
346+
//! See [GET `/v5/analytics`](#get-v5analytics)
347+
//!
321348
//! #### GET `/v5/analytics/for-admin` (auth required)
322349
//!
323350
//! Admin access to the analytics with no restrictions on the keys for filtering.
@@ -332,6 +359,10 @@
332359
//!
333360
//! Response: [`AnalyticsResponse`]
334361
//!
362+
//! ##### Examples
363+
//!
364+
//! See [GET `/v5/analytics`](#get-v5analytics)
365+
//!
335366
//! [`Adapter`]: adapter::Adapter
336367
//! [`Address`]: primitives::Address
337368
//! [`AllowedKey`]: primitives::analytics::query::AllowedKey

sentry/src/routes/campaign.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,6 @@ pub mod update_campaign {
593593

594594
pub mod insert_events {
595595

596-
use std::collections::HashMap;
597-
598596
use crate::{
599597
access::{self, check_access},
600598
analytics,
@@ -608,7 +606,7 @@ pub mod insert_events {
608606
use hyper::{Body, Request, Response};
609607
use primitives::{
610608
balances::{Balances, CheckedState, OverflowError},
611-
sentry::{Event, SuccessResponse},
609+
sentry::{Event, SuccessResponse, InsertEventsRequest},
612610
Address, Campaign, CampaignId, ChainOf, DomainError, UnifiedNum, ValidatorDesc,
613611
};
614612
use slog::{error, Logger};
@@ -642,9 +640,9 @@ pub mod insert_events {
642640

643641
/// POST `/v5/campaign/:id/events`
644642
///
645-
/// The expected request body is `Vec<[Event](primitives::Event)>`
643+
/// Request body (json): [`InsertEventsRequest`]
646644
///
647-
/// The expected Response is [`SuccessResponse`](primitives::sentry::SuccessResponse)
645+
/// Response: [`SuccessResponse`]
648646
pub async fn handle_route<C: Locked + 'static>(
649647
req: Request<Body>,
650648
app: &Application<C>,
@@ -663,17 +661,13 @@ pub mod insert_events {
663661
.expect("request should have a Campaign loaded");
664662

665663
let body_bytes = hyper::body::to_bytes(req_body).await?;
666-
let mut request_body = serde_json::from_slice::<HashMap<String, Vec<Event>>>(&body_bytes)?;
667-
668-
let events = request_body
669-
.remove("events")
670-
.ok_or_else(|| ResponseError::BadRequest("invalid request".to_string()))?;
664+
let request_body = serde_json::from_slice::<InsertEventsRequest>(&body_bytes)?;
671665

672-
let processed = process_events(app, auth, session, campaign_context, events).await?;
666+
process_events(app, auth, session, campaign_context, request_body.events).await?;
673667

674668
Ok(Response::builder()
675669
.header("Content-type", "application/json")
676-
.body(serde_json::to_string(&SuccessResponse { success: processed })?.into())
670+
.body(serde_json::to_string(&SuccessResponse { success: true })?.into())
677671
.unwrap())
678672
}
679673

@@ -683,7 +677,7 @@ pub mod insert_events {
683677
session: &Session,
684678
campaign_context: &ChainOf<Campaign>,
685679
events: Vec<Event>,
686-
) -> Result<bool, ResponseError> {
680+
) -> Result<(), ResponseError> {
687681
let campaign = &campaign_context.context;
688682

689683
// handle events - check access
@@ -732,7 +726,7 @@ pub mod insert_events {
732726
events_success,
733727
);
734728

735-
Ok(true)
729+
Ok(())
736730
}
737731

738732
/// Max retries is `5` after which an error logging message will be recorded.

0 commit comments

Comments
 (0)