Requirements & System Scope
Functional Scope (In-Scope)
- Token Parse and Extract Engine: Scans text strings using performance-optimized regex patterns to extract mention indicators.
- Stateless Username ID Resolution: Cross-references parsed usernames against active user registries to map real IDs.
- Mention Deduplication Rules: Suppresses repeated alarms to prevent duplicate notifications for single posts.
- Trending Hashtag Index Aggregations: Periodically indexes tags and calculates trending weights over custom rolling time windows.
Explicit Boundaries (Out-of-Scope)
- Rich Text Rendering layout wrappers: Omits in-app rich editors, syntax highlights, and markdown parser layout widgets.
- Physical Push Delivery brokers: Simulates notification logs in-memory rather than integrating concrete Apple APNS or Firebase FCM gateways.
Class Diagram & Entity Relationships
Structural layout showing relationships between the parsers, indexing registries, and notification systems:
Loading...
- Post Entity: Holds author IDs, text content, resolved mentioned user ID sets, and extracted hashtag lists.
- HashtagIndex: Links tags to posts, serving as the data source for trend calculations.
Design Patterns & SOLID Principles
- Strategy Pattern: Supports pluggable token parsing logic, allowing tags and mentions to use different extraction algorithms.
- Single Responsibility Principle (SRP): Decouples post formatting, username validation, tag indexing, and notifications into independent services.
- Observer Pattern: Notifies mentioned users out-of-band to prevent notification delivery latency from blocking post publishing.
Core Execution Workflows
Token Resolution & Rolling Time Trends
- Post Token Extraction & Dispatch Pipeline:
- Run regex filters on the post body to extract alphanumeric usernames and tags.
- Verify parsed usernames against the registration index; keep valid user IDs while ignoring invalid ones.
- Store resolved indices in the post record and register hashtags in the indexing directory.
- Send single alert notifications to each uniquely mentioned user ID.
- Rolling Trending Tag Calculation:
- Filter registered posts associated with targeted tags to extract records within the active time window.
- Aggregate active post counts per tag.
- Sort tags by frequency to extract the top-performing trending hashtags.
Concurrency & Thread Safety Strategy
Securing trend engines under high-throughput concurrent post actions:
- Concurrent Graph Mappings: Uses thread-safe tables to prevent registry corruption during simultaneous user sign-ups and posts.
- Non-Blocking Index Logs: Uses concurrent queues to support quick tag indexing without blocking active read streams.
Complete Clean Code Blueprint
Production reference implementations demonstrating token parsing, username resolution, trend computation, and deduplicated notification routing in Java and Python:
// โโโ JAVA BLUEPRINT โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
class Post {
private final String id;
private final String authorId;
private final String content;
private final long createdAtMs;
private final Set<String> mentionedUserIds;
private final Set<String> hashtags;
public Post(String id, String authorId, String content, Set<String> mentionedUserIds, Set<String> hashtags) {
this.id = id;
this.authorId = authorId;
this.content = content;
this.createdAtMs = System.currentTimeMillis();
this.mentionedUserIds = new HashSet<>(mentionedUserIds);
this.hashtags = new HashSet<>(hashtags);
}
public String getId() { return id; }
public String getAuthorId() { return authorId; }
public String getContent() { return content; }
public long getCreatedAtMs() { return createdAtMs; }
public Set<String> getMentionedUserIds() { return Collections.unmodifiableSet(mentionedUserIds); }
public Set<String> getHashtags() { return Collections.unmodifiableSet(hashtags); }
}
class MentionsTaggingService {
private final ConcurrentHashMap<String, Post> posts = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, String> userRegistry = new ConcurrentHashMap<>(); // username -> userId
private final ConcurrentHashMap<String, ConcurrentLinkedQueue<String>> hashtagIndex = new ConcurrentHashMap<>(); // hashtag -> list of postIds
private final ConcurrentLinkedQueue<String> notificationLog = new ConcurrentLinkedQueue<>();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private static final Pattern MENTION_PATTERN = Pattern.compile("@([a-zA-Z0-9_]+)");
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#([a-zA-Z0-9_]+)");
public void registerUser(String username, String userId) {
rwLock.writeLock().lock();
try {
userRegistry.put(username.toLowerCase(), userId);
} finally {
rwLock.writeLock().unlock();
}
}
// Publish Post with Token Parsing & Notification dispatching
public Post createPost(String authorId, String content) {
String postId = UUID.randomUUID().toString();
rwLock.readLock().lock();
Set<String> mentionedUserIds;
try {
// Parse @mentions and #hashtags
mentionedUserIds = parseMentions(content);
} finally {
rwLock.readLock().unlock();
}
Set<String> hashtags = parseHashtags(content);
Post newPost = new Post(postId, authorId, content, mentionedUserIds, hashtags);
posts.put(postId, newPost);
// Populate Hashtag Index
for (String tag : hashtags) {
hashtagIndex.computeIfAbsent(tag.toLowerCase(), k -> new ConcurrentLinkedQueue<>()).add(postId);
}
// Deliver Deduplicated Mention Notifications
for (String userId : mentionedUserIds) {
triggerNotification(userId, postId);
}
return newPost;
}
// O(K log K) trending hashtags by active volume in window
public List<Map.Entry<String, Long>> getTrendingHashtags(long windowMs, int topN) {
long limitTime = System.currentTimeMillis() - windowMs;
return hashtagIndex.entrySet().stream()
.map(entry -> {
long activeCount = entry.getValue().stream()
.map(posts::get)
.filter(Objects::nonNull)
.filter(post -> post.getCreatedAtMs() >= limitTime)
.count();
return new AbstractMap.SimpleEntry<>(entry.getKey(), activeCount);
})
.filter(entry -> entry.getValue() > 0)
.sorted((a, b) -> Long.compare(b.getValue(), a.getValue()))
.limit(topN)
.collect(Collectors.toList());
}
public Post getPost(String postId) {
return posts.get(postId);
}
public List<String> getNotificationLog() {
return new ArrayList<>(notificationLog);
}
private Set<String> parseMentions(String text) {
Set<String> resolvedIds = new HashSet<>();
Matcher matcher = MENTION_PATTERN.matcher(text);
while (matcher.find()) {
String username = matcher.group(1).toLowerCase();
String userId = userRegistry.get(username);
if (userId != null) {
resolvedIds.add(userId); // Deduplicates automatically
}
}
return resolvedIds;
}
private Set<String> parseHashtags(String text) {
Set<String> hashtags = new HashSet<>();
Matcher matcher = HASHTAG_PATTERN.matcher(text);
while (matcher.find()) {
String tag = matcher.group(1).toLowerCase();
hashtags.add(tag); // Deduplicates automatically
}
return hashtags;
}
private void triggerNotification(String userId, String postId) {
String logEntry = "NOTIFY -> User: " + userId + " was mentioned in Post: " + postId;
notificationLog.offer(logEntry);
System.out.println(logEntry);
}
}
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("=== JAVA MENTIONS & TAGGING DEMO ===");
MentionsTaggingService service = new MentionsTaggingService();
// Register active platform users
service.registerUser("Alice", "user_101");
service.registerUser("Bob", "user_102");
service.registerUser("Charlie", "user_103");
// Alice publishes a post mentioning Bob and Charlie
System.out.println("Alice publishes a post...");
Post post1 = service.createPost("user_101", "Hey @Bob and @Charlie! Check this out! #coding #systemdesign");
System.out.println("Post ID: " + post1.getId());
System.out.println("Mentioned User IDs: " + post1.getMentionedUserIds());
System.out.println("Hashtags extracted: " + post1.getHashtags());
// Bob publishes a post with design tags
System.out.println("\nBob publishes a post...");
Post post2 = service.createPost("user_102", "Working on a new LLD problem. #coding #java");
// Check trending hashtags over last 1 minute
System.out.println("\nFetching trending hashtags...");
List<Map.Entry<String, Long>> trends = service.getTrendingHashtags(60000, 5);
for (Map.Entry<String, Long> trend : trends) {
System.out.println(" - Tag: #" + trend.getKey() + " | Count: " + trend.getValue());
}
System.out.println("\nNotification Logs:");
System.out.println(service.getNotificationLog());
System.out.println("=== END OF DEMO ===");
}
}
Review
Help Us Improve
How helpful was this walkthrough?
Click a star to rate. We actively use this feedback to refine and update our system design content.
Placeholder
Discussion
Share your thoughts, ask questions, or help others.
Loading comments...