Skip to content

Cassandra demo app - An email application where millions of users can send emails/messages to one another

Notifications You must be signed in to change notification settings

naren-jha/inbox-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

inbox-app

Cassandra Docs

--

App Design Doc:

End result

After User SignUp: image

Empty folder (no sent items yet): image

Email View: image

Composing a new email: image

A new email lands in all receiving user's inbox: image

And is also kept in sent items of sender user: image

Email view: image

Cassandra data model so far:

  • These are the two high-level goals for data modeling in Cassandra:
    1. Spread data evenly around the cluster
    2. Minimize the number of partitions you read from

Lets see what all tables are created. If we describe main cluster, we can see all the table schema.

token@cqlsh> use main;
token@cqlsh:main> describe main;

CREATE KEYSPACE main WITH replication = {'class': 'NetworkTopologyStrategy', 'asia-south1': '3'}  AND durable_writes = true;

CREATE TABLE main.folders_by_user (
    user_id text,
    created_at_uuid uuid,
    label text,
    color text,
    PRIMARY KEY (user_id, created_at_uuid, label)
) WITH CLUSTERING ORDER BY (created_at_uuid ASC, label ASC)
    AND additional_write_policy = '99PERCENTILE'
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair = 'BLOCKING'
    AND speculative_retry = '99PERCENTILE';

CREATE TABLE main.messages_by_id (
    id uuid PRIMARY KEY,
    body text,
    "from" text,
    subject text,
    "to" list<text>
) WITH additional_write_policy = '99PERCENTILE'
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair = 'BLOCKING'
    AND speculative_retry = '99PERCENTILE';

CREATE TABLE main.messages_by_user_folder (
    user_id text,
    label text,
    created_at_uuid uuid,
    "from" text,
    subject text,
    unread boolean,
    PRIMARY KEY ((user_id, label), created_at_uuid)
) WITH CLUSTERING ORDER BY (created_at_uuid DESC)
    AND additional_write_policy = '99PERCENTILE'
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair = 'BLOCKING'
    AND speculative_retry = '99PERCENTILE';

data in tables and end result:

folders_by_user

image

messages_by_id

image

messages_by_user_folder

image

Sending email to multiple users at a time image

New email received: image

image

DB console after this new message: image

Folder wise unread counter

  • counter tables in Cassandra has to be a dedicated table.
  • i.e., columns in a counter table can be either primarykey (partitioning key or clustering key) column, or counter column itself
  • that means, you cannot have non-priparykey, non-counter column in a counter table.
  • you can run increment/decrement queries on counter columns of a counter table, like - update COUNTER_TABLE_NAME set COUNTER_COL_NAME = COUNTER_COL_NAME + 1 where SOME_OTHER_COL = SOME_VAL note that here the record does not have to exist in advance with matching 'where clause'. If the record with the given where clause does not exist, cassandra will create a new entry with initial value for all counter columns as 0. So in this case if there is no entry for SOME_OTHER_COL = SOME_VAL when the query is executed, then cassandra will create a new entry and the value for COUNTER_COL_NAME for that entry will be updated from 0 to 1.

maintaining unread email counter per folder image

marking message read/unread: image

table data: image

About

Cassandra demo app - An email application where millions of users can send emails/messages to one another

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published