Interview Question: Design a low level RSS feed
--
Really Simple Syndication or RSS is a web feed, that allow users to be notified when a website is update a specific topic.
For example: for a news website, like (https://www.ynet.co.il/), Jenny would like to be notified when there is a travel update or a politics update. Yossi would like to be notified when there is a politics update or a sport update.
So the RSS feeder should manage a Topics list, each Topic should manage its Subscribers, and each Subscriber should handle its own notification handle.
RSS broker is responsible for holding a reference for all the topics (as a hashmap for O(1) accessing and avoid duplicates):
public class RSSBroker
{
private IDictionary<string, TopicObservable> _topics;
public RSSBroker()
{
this._topics = new Dictionary<string, TopicObservable>();
} public void AddTopic(TopicObservable topic)
{
this._topics.TryAdd(topic.Id, topic);
} public void UnsubscribeFromTopic(string id, UserObserver observer)
{
if (this._topics.ContainsKey(id))
this._topics[id].Unsubscribe(observer);
} public void RegisterToTopic(string id, UserObserver observer)
{
if (this._topics.ContainsKey(id))
this._topics[id].Register(observer);
}
}
The Topic Observable is responsible for managing the clients observers, and send them a notify them when needed:
public class TopicObservable
{
private Dictionary<Guid, UserObserver> _observers = new Dictionary<Guid, UserObserver>();
public string Id { get; internal set; } public TopicObservable(string id)
{
this.Id = id;
} public void Register(UserObserver observer)
{
this._observers.TryAdd(observer.Id, observer);
}
public void Send(string message)
{
foreach (var observer in this._observers)
{
observer.Value.HandleNotification(this.Id, message);
}
} public void Unsubscribe(UserObserver observer)
{
if (this._observers.ContainsKey(observer.Id))
this._observers.Remove(observer.Id);
}
}
The user observer:
public class UserObserver
{
public string Name { get; internal set; }
public Guid Id { get; internal set; }
public UserObserver(string name)
{
this.Id = Guid.NewGuid();
this.Name = name;
} public void HandleNotification(string topicId, string message)
{
Console.WriteLine($"Hello {this.Name}! you have a new RSS event from {topicId}");
Console.WriteLine($"Message: {message}");
}
}
The Usage:
RSSBroker broker = new RSSBroker();TopicObservable politics = new TopicObservable("Politics");
TopicObservable travel = new TopicObservable("Travel");
TopicObservable tech = new TopicObservable("Tech");broker.AddTopic(politics);
broker.AddTopic(travel);
broker.AddTopic(tech);var jenny = new UserObserver("Jenny");
var yossi = new UserObserver("Yossi");broker.RegisterToTopic("Politics", jenny);
broker.RegisterToTopic("Travel", jenny);broker.RegisterToTopic("Politics", yossi);
broker.RegisterToTopic("Tech", yossi);politics.Send("Palestinian elections are attempt to settle political landscape");
travel.Send("Israel is surprising location for digital nomads");
tech.Send("Israel says developing new Arrow- 4 ballistic missile shield with U.S.");
Will Output:
Hello Jenny! you have a new RSS event from Politics
Message: Palestinian elections are attempt to settle political landscape
Hello Yossi! you have a new RSS event from Politics
Message: Palestinian elections are attempt to settle political landscape
Hello Jenny! you have a new RSS event from Travel
Message: Israel is surprising location for digital nomads
Hello Yossi! you have a new RSS event from Tech
Message: Israel says developing new Arrow- 4 ballistic missile shield with U.S.