Skip to content

Commit e5121b3

Browse files
authored
Merge pull request #26 from dorianim/chore/capsulate-redis-handling
Chore: capsulate redis operations into respository module
2 parents dbdc6b3 + 243e112 commit e5121b3

File tree

12 files changed

+639
-189
lines changed

12 files changed

+639
-189
lines changed

src/main.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use tower_http::cors::{Any, CorsLayer};
77
use tower_http::trace::TraceLayer;
88
use tracing::Span;
99
mod color;
10-
mod routes;
1110
mod models;
11+
mod redis_migrations;
12+
mod repository;
13+
mod routes;
1214

1315
use models::*;
1416

15-
use tokio::sync::broadcast;
16-
17-
17+
use crate::repository::Repository;
1818

1919
#[tokio::main]
2020
async fn main() {
@@ -23,31 +23,24 @@ async fn main() {
2323
.allow_headers(Any)
2424
.allow_methods(Any);
2525

26-
let redis_string = env::var("REDIS_STRING").expect("REDIS_STRING is not set");
27-
let jwt_key = env::var("JWT_KEY").expect("JWT_KEY is not set");
28-
let client = redis::Client::open(redis_string.to_owned()).expect("Could not connect to redis");
29-
let manager = redis::aio::ConnectionManager::new(client.clone())
30-
.await
31-
.unwrap();
32-
3326
let instance_properties = InstanceProperties {
3427
demo: env::var("INSTANCE_DEMO").unwrap_or("false".to_owned()) == "true",
3528
donation: env::var("INSTANCE_DONATION_PAYPAL")
3629
.map(|id| Some(vec![DonationMethod::PayPal(id)]))
3730
.unwrap_or(None),
31+
s3_host: env::var("S3_HOST").unwrap_or("".to_owned()),
3832
};
33+
let jwt_key = env::var("JWT_KEY").expect("JWT_KEY is not set");
34+
let redis_string = env::var("REDIS_STRING").expect("REDIS_STRING is not set");
3935

40-
let (redis_task_tx, redis_task_rx) = broadcast::channel::<Timer>(10);
36+
let repository = Repository::new(redis_string).await;
4137

4238
let state: SharedState = Arc::new(AppState {
43-
redis: manager.clone(),
39+
repository,
4440
jwt_key,
4541
instance_properties,
46-
redis_task_rx,
4742
});
4843

49-
routes::ws::spawn_global_redis_listener_task(manager, client, redis_task_tx);
50-
5144
let app = Router::new()
5245
.nest("/api/ws", routes::ws::routes())
5346
.nest("/api/timer", routes::timer::routes(state.clone()))

src/models.rs

Lines changed: 52 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,6 @@
1+
use crate::repository::{DisplayOptions, Repository, Segment, Timer, TimerMetadata};
12
use serde::{Deserialize, Serialize};
2-
use crate::color::Color;
33
use std::sync::Arc;
4-
use tokio::sync::broadcast;
5-
6-
//main.rs
7-
fn default_zero() -> u32 {
8-
0
9-
}
10-
11-
#[derive(Serialize, Deserialize, Clone, Debug)]
12-
pub struct Segment {
13-
label: String,
14-
time: u32,
15-
sound: bool,
16-
color: Option<Color>,
17-
#[serde(default = "default_zero")]
18-
count_to: u32,
19-
}
20-
21-
#[derive(Serialize, Deserialize, Clone, Debug)]
22-
pub enum PreStartBehaviour {
23-
ShowZero,
24-
RunNormally,
25-
}
26-
27-
impl Default for PreStartBehaviour {
28-
fn default() -> Self {
29-
PreStartBehaviour::ShowZero
30-
}
31-
}
32-
33-
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
34-
pub struct DisplayOptions {
35-
#[serde(default)]
36-
clock: bool,
37-
#[serde(default)]
38-
pre_start_behaviour: PreStartBehaviour,
39-
}
40-
41-
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
42-
pub struct Timer {
43-
// Return after TimerRequest
44-
pub segments: Vec<Segment>,
45-
pub repeat: bool,
46-
pub display_options: Option<DisplayOptions>,
47-
pub start_at: u64,
48-
pub stop_at: Option<u64>,
49-
pub password: String,
50-
pub id: String, // 5 random chars
51-
}
524

535
#[derive(Serialize, Clone)]
546
#[serde(tag = "type", content = "data")]
@@ -60,17 +12,16 @@ pub enum DonationMethod {
6012
pub struct InstanceProperties {
6113
pub demo: bool,
6214
pub donation: Option<Vec<DonationMethod>>,
15+
pub s3_host: String,
6316
}
6417

6518
pub type SharedState = Arc<AppState>;
6619
pub struct AppState {
67-
pub redis: redis::aio::ConnectionManager,
20+
pub repository: Repository,
6821
pub jwt_key: String,
6922
pub instance_properties: InstanceProperties,
70-
pub redis_task_rx: broadcast::Receiver<Timer>,
7123
}
7224

73-
7425
//timer.rs
7526

7627
#[derive(Serialize, Deserialize, Debug)]
@@ -81,6 +32,7 @@ pub struct TimerResponse {
8132
pub display_options: DisplayOptions,
8233
pub start_at: u64,
8334
pub stop_at: Option<u64>,
35+
pub metadata: TimerMetadata,
8436
}
8537

8638
impl Into<TimerResponse> for Timer {
@@ -89,9 +41,10 @@ impl Into<TimerResponse> for Timer {
8941
segments: self.segments,
9042
id: self.id,
9143
repeat: self.repeat,
92-
display_options: self.display_options.unwrap_or(DisplayOptions::default()),
44+
display_options: self.display_options,
9345
start_at: self.start_at,
9446
stop_at: self.stop_at,
47+
metadata: self.metadata,
9548
}
9649
}
9750
}
@@ -104,20 +57,36 @@ pub struct TimerCreationResponse {
10457

10558
#[derive(Serialize, Deserialize)]
10659
pub struct TimerCreationRequest {
107-
// Get from User
10860
pub segments: Vec<Segment>,
10961
pub id: String,
11062
pub password: String,
11163
pub repeat: bool,
11264
pub start_at: u64,
65+
pub metadata: TimerMetadata,
66+
pub display_options: DisplayOptions,
67+
}
68+
69+
impl TimerCreationRequest {
70+
pub fn into(self, hashed_password: String) -> Timer {
71+
Timer {
72+
segments: self.segments,
73+
repeat: self.repeat,
74+
display_options: self.display_options,
75+
start_at: self.start_at,
76+
stop_at: None,
77+
password: hashed_password,
78+
id: self.id,
79+
metadata: self.metadata,
80+
}
81+
}
11382
}
11483

11584
#[derive(Serialize, Deserialize)]
11685
pub struct TimerUpdateRequest {
117-
// Get from User
11886
pub segments: Vec<Segment>,
11987
pub repeat: bool,
120-
pub display_options: Option<DisplayOptions>,
88+
pub display_options: DisplayOptions,
89+
pub metadata: TimerMetadata,
12190
pub start_at: u64,
12291
pub stop_at: Option<u64>,
12392
}
@@ -139,3 +108,30 @@ pub struct Claims {
139108
pub struct TokenResponse {
140109
pub token: String,
141110
}
111+
112+
///
113+
/// Websocket
114+
///
115+
116+
#[derive(Serialize, Deserialize, Debug)]
117+
pub struct WsTimerResponse {
118+
pub segments: Vec<Segment>,
119+
pub id: String,
120+
pub repeat: bool,
121+
pub display_options: DisplayOptions,
122+
pub start_at: u64,
123+
pub stop_at: Option<u64>,
124+
}
125+
126+
impl Into<WsTimerResponse> for Timer {
127+
fn into(self) -> WsTimerResponse {
128+
WsTimerResponse {
129+
segments: self.segments,
130+
id: self.id,
131+
repeat: self.repeat,
132+
display_options: self.display_options,
133+
start_at: self.start_at,
134+
stop_at: self.stop_at,
135+
}
136+
}
137+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use serde::Deserialize;
2+
3+
use crate::repository::DisplayOptions;
4+
5+
use super::pre_start_behaviour::RedisPreStartBehaviour;
6+
7+
#[derive(Deserialize, Clone)]
8+
#[serde(untagged)]
9+
pub enum RedisDisplayOptions {
10+
V0(DisplayOptionsV0),
11+
}
12+
13+
impl Into<DisplayOptions> for RedisDisplayOptions {
14+
fn into(self) -> DisplayOptions {
15+
match self {
16+
RedisDisplayOptions::V0(v0) => v0.into(),
17+
}
18+
}
19+
}
20+
21+
impl Into<DisplayOptions> for Option<RedisDisplayOptions> {
22+
fn into(self) -> DisplayOptions {
23+
self.map(|o| o.into()).unwrap_or(DisplayOptions::default())
24+
}
25+
}
26+
27+
#[derive(Deserialize, Clone)]
28+
pub struct DisplayOptionsV0 {
29+
#[serde(default)]
30+
clock: bool,
31+
#[serde(default)]
32+
pre_start_behaviour: RedisPreStartBehaviour,
33+
}
34+
35+
impl Into<DisplayOptions> for DisplayOptionsV0 {
36+
fn into(self) -> DisplayOptions {
37+
DisplayOptions {
38+
clock: self.clock,
39+
pre_start_behaviour: self.pre_start_behaviour.into(),
40+
}
41+
}
42+
}
43+
44+
impl Into<DisplayOptions> for Option<DisplayOptionsV0> {
45+
fn into(self) -> DisplayOptions {
46+
self.map(|o| o.into()).unwrap_or(DisplayOptions::default())
47+
}
48+
}

src/redis_migrations/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mod display_options;
2+
mod pre_start_behaviour;
3+
mod segment;
4+
mod tests;
5+
mod timer;
6+
mod timer_metadata;
7+
8+
pub use timer::RedisTimer;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use serde::Deserialize;
2+
3+
use crate::repository::PreStartBehaviour;
4+
5+
#[derive(Deserialize, Clone)]
6+
#[serde(untagged)]
7+
pub enum RedisPreStartBehaviour {
8+
V1(PreStartBehaviourV1),
9+
V0(PreStartBehaviourV0),
10+
}
11+
12+
impl Into<PreStartBehaviour> for RedisPreStartBehaviour {
13+
fn into(self) -> PreStartBehaviour {
14+
match self {
15+
RedisPreStartBehaviour::V0(v0) => v0.into(),
16+
RedisPreStartBehaviour::V1(v1) => v1.into(),
17+
}
18+
}
19+
}
20+
21+
impl Default for RedisPreStartBehaviour {
22+
fn default() -> Self {
23+
Self::V1(PreStartBehaviourV1::default())
24+
}
25+
}
26+
27+
/// === V1 ===
28+
#[derive(Deserialize, Clone)]
29+
pub enum PreStartBehaviourV1 {
30+
ShowFirstSegment,
31+
ShowLastSegment,
32+
RunNormally,
33+
}
34+
35+
impl Default for PreStartBehaviourV1 {
36+
fn default() -> Self {
37+
PreStartBehaviourV1::ShowFirstSegment
38+
}
39+
}
40+
41+
impl Into<PreStartBehaviour> for PreStartBehaviourV1 {
42+
fn into(self) -> PreStartBehaviour {
43+
match self {
44+
PreStartBehaviourV1::RunNormally => PreStartBehaviour::RunNormally,
45+
PreStartBehaviourV1::ShowFirstSegment => PreStartBehaviour::ShowFirstSegment,
46+
PreStartBehaviourV1::ShowLastSegment => PreStartBehaviour::ShowLastSegment,
47+
}
48+
}
49+
}
50+
51+
/// === V0 ===
52+
#[derive(Deserialize, Clone)]
53+
pub enum PreStartBehaviourV0 {
54+
ShowZero,
55+
RunNormally,
56+
}
57+
58+
impl Default for PreStartBehaviourV0 {
59+
fn default() -> Self {
60+
PreStartBehaviourV0::ShowZero
61+
}
62+
}
63+
64+
impl Into<PreStartBehaviour> for PreStartBehaviourV0 {
65+
fn into(self) -> PreStartBehaviour {
66+
match self {
67+
PreStartBehaviourV0::RunNormally => PreStartBehaviour::RunNormally,
68+
PreStartBehaviourV0::ShowZero => PreStartBehaviour::ShowFirstSegment,
69+
}
70+
}
71+
}

src/redis_migrations/segment.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use serde::Deserialize;
2+
3+
use crate::{color::Color, repository::Segment};
4+
5+
#[derive(Deserialize, Clone)]
6+
#[serde(untagged)]
7+
pub enum RedisSegment {
8+
V0(SegmentV0),
9+
}
10+
11+
impl Into<Segment> for RedisSegment {
12+
fn into(self) -> Segment {
13+
match self {
14+
RedisSegment::V0(v0) => v0.into(),
15+
}
16+
}
17+
}
18+
19+
fn default_zero() -> u32 {
20+
0
21+
}
22+
23+
#[derive(Deserialize, Clone)]
24+
pub struct SegmentV0 {
25+
label: String,
26+
time: u32,
27+
sound: bool,
28+
color: Option<Color>,
29+
#[serde(default = "default_zero")]
30+
count_to: u32,
31+
}
32+
33+
impl Into<Segment> for SegmentV0 {
34+
fn into(self) -> Segment {
35+
Segment {
36+
label: self.label,
37+
time: self.time,
38+
sound: self.sound,
39+
color: self.color,
40+
count_to: self.count_to,
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)