Monday, May 5, 2025

What is Cache Sync

Lets assume a toy store web site has cache system that has cahced the product catalog  

If the product catalog is cached, you must ensure cache consistency when the catalog is updated. This is known as cache invalidation or cache update, and it’s one of the hardest problems in caching.


✅ Ways to Keep Cache in Sync When Product Catalog Updates:


๐Ÿ”„ 1. Write-through Cache

  • How it works: Write to both the database and the cache simultaneously.

  • Pros: Always in sync.

  • Cons: Slightly slower write operations.

function updateProduct(productId, data):
    database.update(productId, data)
    cache.set("product:" + productId, data)

๐Ÿงน 2. Cache Invalidation (on Update/Delete)

  • How it works: Invalidate (delete) the cache entry when the DB is updated.

  • Pros: Ensures fresh data on next read.

  • Cons: Next read will have to re-fetch from DB (cache miss).

function updateProduct(productId, data):
    database.update(productId, data)
    cache.delete("product:" + productId) // Invalidate

๐Ÿ“ฆ 3. Event-based Cache Update

  • How it works: Emit an event when products are updated. A listener updates or invalidates the cache.

  • Pros: Decouples logic; scales better in distributed systems.

  • Cons: More complex (needs message broker like Kafka, RabbitMQ)


⏱️ 4. Time-based Expiry (TTL)

  • How it works: Let cache entries expire after a short time (e.g., 5 minutes).

  • Pros: Simple to implement.

  • Cons: Might serve stale data for a short while.


๐Ÿง  Best Practice: Combine Methods

For a toy store, you might:

  • Use write-through cache for product edits via admin panel.

  • Use TTL for less critical items like "top 10 products."

  • Invalidate cache for specific product IDs when updates happen.

  • Rebuild full catalog cache periodically or via admin trigger.


Shared Memory Usage Between Qt UI and Separate process

Shared Memory Usage Between Qt UI and A.exe


๐Ÿงฉ Application Architecture Overview

Component Role
A.exe External process writing status/log/values to shared memory
Qt UI GUI process that starts/stops A.exe, reads its output/status from shared memory
Shared Memory Used for bidirectional communication (if needed), e.g., variables or status flags
QSystemSemaphore Synchronizes access to shared memory to avoid race conditions

๐Ÿ“ฆ Shared Memory Setup

1. Define Shared Data Structure (common to both)

// shared_data.h
#ifndef SHARED_DATA_H
#define SHARED_DATA_H

struct SharedData {
    int statusCode;
    float someValue;
    char log[512];
};

#endif

2. Shared Memory and Semaphore Keys

Use the same names in both A.exe and the Qt app:

const QString SHARED_MEM_KEY = "MySharedMemoryKey";
const QString SEMAPHORE_KEY = "MySharedMemorySemaphore";
const int SHARED_MEM_SIZE = sizeof(SharedData);

๐Ÿ—️ Where is Shared Memory Created?

  • The Qt UI should create the shared memory on startup (before starting A.exe).

  • A.exe will just attach to it.

In Qt UI:

QSharedMemory sharedMemory(SHARED_MEM_KEY);
QSystemSemaphore semaphore(SEMAPHORE_KEY, 1);

// Create shared memory segment
if (!sharedMemory.create(SHARED_MEM_SIZE)) {
    if (sharedMemory.error() == QSharedMemory::AlreadyExists) {
        sharedMemory.attach();  // Fallback
    }
}

✏️ Writing to Shared Memory (A.exe)

In A.exe (after attaching):

QSharedMemory sharedMemory(SHARED_MEM_KEY);
QSystemSemaphore semaphore(SEMAPHORE_KEY, 1);

if (!sharedMemory.attach()) {
    // handle error
}

semaphore.acquire();           // Lock semaphore
sharedMemory.lock();           // Lock memory

SharedData* data = static_cast<SharedData*>(sharedMemory.data());
data->statusCode = 200;
data->someValue = 42.0f;
strcpy(data->log, "Running OK");

sharedMemory.unlock();
semaphore.release();

๐Ÿ‘️ Reading from Shared Memory (Qt UI)

Periodically read from a timer, e.g., every 1s:

semaphore.acquire();           // Lock semaphore
sharedMemory.lock();           // Lock memory

SharedData* data = static_cast<SharedData*>(sharedMemory.constData());
int status = data->statusCode;
float value = data->someValue;
QString logText = QString::fromUtf8(data->log);

sharedMemory.unlock();
semaphore.release();

๐Ÿ›‘ Cleanup

Detach when done:

sharedMemory.detach();

๐Ÿ” Synchronization Flow

Step Action
1 Acquire QSystemSemaphore (blocks others)
2 Lock shared memory (sharedMemory.lock())
3 Read or write data
4 Unlock shared memory
5 Release QSystemSemaphore

๐Ÿ›ก️ Key Best Practices

✅ Always lock memory after acquiring a semaphore
✅ Only one process creates shared memory (Qt UI)
✅ Others should only attach()
✅ Use detach() on exit
✅ Wrap read/write in try/catch if stability is critical



Sunday, May 4, 2025

What is Caching Data

Caching data to reduce expensive or frequent database queries, it's common to cache the following data types or structures:


1. Lookup Tables / Reference Data

  • Country lists, currency codes, language options, etc.

  • Usually small, rarely change.

  • Cached as: Map / Object / Dictionary

2. User Sessions / Auth Tokens

  • User-specific session or authentication information.

  • Cached as: Key-Value Pairs, e.g., {userId: sessionInfo}

3. Frequently Accessed Business Data

  • Product catalogs, user profiles, configuration settings, etc.

  • Cached as: JSON Objects, Lists, or Serialized Records

4. Query Results

  • The result of complex or expensive SQL queries.

  • Cached as: Serialized Result Sets, e.g., JSON or binary formats

5. Computed/Derived Data

  • Aggregated metrics, scores, or statistics.

  • Cached as: Numbers, Objects, or Strings

6. HTML Fragments / Page Chunks

  • Rendered UI elements like menus, sidebars, etc.

  • Cached as: Strings

7. API Responses

  • Cached third-party API responses to avoid redundant calls.

  • Cached as: JSON/XML Strings or Deserialized Objects


Common Caching Tools

  • In-memory: Redis, Memcached, Ehcache

  • Client-side: Browser localStorage/sessionStorage

  • Application-level: Guava Cache (Java), @Cacheable (Spring), Angular/React state services


For a toy store website, caching can dramatically improve performance and reduce database load. Here's a breakdown of what you can cache and where it might be best cached:

1. Product Catalog

What to cache:

  • Toy listings, categories, filters

  • Product details (name, price, description, image URL)

Where to cache:

  • In-memory (e.g., Redis, in-app memory) for fast access

  • Browser cache for static content like images


๐Ÿงธ 2. Category and Filter Data

What to cache:

  • List of categories (e.g., Age 0-3, Educational, Dolls)

  • Available brands, age ranges, price brackets

Where to cache:

  • Application-level cache (e.g., in-memory or Redis)

  • CDN/static file for rarely changing filters


๐Ÿ‘ค 3. User Session and Cart

What to cache:

  • User login session, preferences

  • Shopping cart data

Where to cache:

  • Server-side session cache (e.g., Redis)

  • Local storage or cookies on the client for carts


๐Ÿ’ฐ 4. Promotions and Pricing Rules

What to cache:

  • Discount rules, active coupon codes, seasonal offers

Where to cache:

  • In-memory with short TTL (Time To Live)


๐ŸŒ 5. Frequently Accessed Pages

What to cache:

  • Homepage layout (banners, top products)

  • Bestsellers, new arrivals, etc.

Where to cache:

  • HTML fragment cache or full-page cache (e.g., Varnish, NGINX)

  • CDN for static parts


๐Ÿงพ 6. Order Status and History (per user)

What to cache:

  • Recently placed orders, shipping status

Where to cache:

  • Short-lived cache for recently viewed orders

  • Could be cached in Redis with keys like orders:userId


⚠️ Cache with care:

  • Inventory/stock levels can be cached, but with short TTL (or use a hybrid cache+DB approach) to avoid overselling.

  • Personalized recommendations can be cached per user or user segment.


LeetCode C++ Cheat Sheet June

๐ŸŽฏ Core Patterns & Representative Questions 1. Arrays & Hashing Two Sum – hash map → O(n) Contains Duplicate , Product of A...