-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: broadcast news through websockets when created
- Loading branch information
1 parent
4045499
commit 188ba64
Showing
14 changed files
with
186 additions
and
22 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,50 @@ | ||
import React, { useEffect } from 'react'; | ||
import api from '../services/api'; | ||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import api, { News } from '../services/api'; | ||
|
||
interface Props {} | ||
|
||
const WebSocketComponent = (_: Props) => { | ||
useEffect(() => { | ||
const connDestruct = api.connectWs((event) => { | ||
const [lastNews, setLastNews] = useState<News[]>([]); | ||
|
||
const addLastNews = useCallback( | ||
(event: MessageEvent<any>) => { | ||
try { | ||
const news = JSON.parse(event.data); | ||
|
||
setLastNews([news, ...lastNews]); | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
console.log('WebSocket message received:', event.data); | ||
}); | ||
}, | ||
[lastNews] | ||
); | ||
|
||
useEffect(() => { | ||
const connDestruct = api.connectWs(addLastNews); | ||
|
||
// Clean up the WebSocket connection when the component unmounts | ||
return connDestruct; | ||
}, []); | ||
|
||
return <span aria-description="websocket-placeholder"></span>; | ||
return ( | ||
<> | ||
{lastNews.length !== 0 ? ( | ||
<> | ||
<h2>Last News</h2> | ||
{lastNews.map((news) => { | ||
return ( | ||
<p> | ||
{news.title} ({news.author}) {news.publish_date} | ||
</p> | ||
); | ||
})} | ||
</> | ||
) : ( | ||
<></> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default WebSocketComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use crate::{ | ||
config::Config, models::news::News, | ||
repositories::subscription_repository::SubscriptionRepository, | ||
}; | ||
use actix::Addr; | ||
use log::{debug, error, info}; | ||
use rdkafka::consumer::Consumer; | ||
use rdkafka::consumer::StreamConsumer; | ||
use rdkafka::Message; | ||
use std::{error::Error, sync::Arc}; | ||
use utils::{ | ||
broker, | ||
http::websockets::ws_server::{SessionMessage, WebsocketServer}, | ||
}; | ||
|
||
pub async fn setup_news_created_subscriber( | ||
config: &Config, | ||
ws: Addr<WebsocketServer>, | ||
subscription_repo: Arc<dyn SubscriptionRepository>, | ||
) -> Result<(), Box<dyn Error>> { | ||
let consumer: StreamConsumer = broker::create_consumer(config.kafka_url.clone()); | ||
|
||
consumer | ||
.subscribe(&["news_created"]) | ||
.expect("Error subscribing to topic"); | ||
|
||
// Consume messages from the subscribed topic | ||
loop { | ||
match consumer.recv().await { | ||
Ok(message) => { | ||
let payload = message.payload_view::<str>(); | ||
match payload { | ||
Some(Ok(payload)) => { | ||
info!("Received message: {}", payload); | ||
let news: News = | ||
serde_json::from_str(payload).expect("Failed to convert JSON string"); | ||
|
||
let result = subscription_repo.list_by_feed(news.feed_id); | ||
|
||
match result { | ||
Ok(subscriptions) => { | ||
for s in subscriptions { | ||
debug!("sending message to socket {}", s.user_id); | ||
ws.do_send(SessionMessage { | ||
id: s.user_id.to_string(), | ||
message: payload.to_string(), | ||
}); | ||
} | ||
} | ||
Err(err) => { | ||
error!( | ||
"failed getting subscriptions from database: {}", | ||
err.message | ||
); | ||
} | ||
} | ||
} | ||
Some(Err(_)) => error!("Error deserializing message payload"), | ||
None => error!("Empty message payload"), | ||
} | ||
} | ||
Err(_) => error!("Error deserializing message payload"), | ||
} | ||
} | ||
} |
Oops, something went wrong.