Simple Key-Value storage usage in AWS::DynamoDB

Many times, all you need is a simple storage in the cloud to store a typical Key-Value pair (which is usually very handy for many applications). The example below does that using AWS Dynamo DB. To exemplify I'm storing there all the lottery numbers since 2002. I'm removing my access ID and secret key - those you need to get from AWS. I find the syntax fairly straightforward and intuitive. Although I didn't try Azure, AWS didn't perform as fast as I expected for the insertion, taking several minutes to add just few thousand records. But it worked, and the code is down below, cheers, ACC.


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using System.IO;

class Program
{
    private static readonly string AccessKeyId = "HIDDEN";
    private static readonly string SecretAccessKey = "HIDDEN";
    private static readonly string TableName = "KeyValueStore";
    private static AmazonDynamoDBClient client;

    static async Task Main(string[] args)
    {
        try
        {
            InitializeDynamoDBClient();
            await CreateTableIfNotExistsAsync();

            Console.WriteLine("Populating Key-Value with all Lottery Numbers since 2002...");
            FileInfo fi = new FileInfo("Lottery_Mega_Millions_Winning_Numbers__Beginning_2002.csv");
            StreamReader sr = fi.OpenText();
            int count = 0;
            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine();
                string[] parts = line.Split(new char[] {','},  StringSplitOptions.RemoveEmptyEntries);
                string key = parts[0];
                string value = parts[1];
                await AddKeyValuePair(key, value);
                count++;
            }
            sr.Close();
            Console.WriteLine("Done. Added: {0} records", count);

            while (true)
            {
                Console.WriteLine("\nChoose an operation:");
                Console.WriteLine("1. Add a key-value pair");
                Console.WriteLine("2. Get a value by key");
                Console.WriteLine("3. Exit");

                string choice = Console.ReadLine();

                switch (choice)
                {
                    case "1":
                        await AddKeyValuePair();
                        break;
                    case "2":
                        await GetValueByKey();
                        break;
                    case "3":
                        return;
                    default:
                        Console.WriteLine("Invalid choice. Please try again.");
                        break;
                }
            }
        }
        catch (AmazonDynamoDBException e)
        {
            Console.WriteLine($"DynamoDB Error: {e.Message}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }

    private static void InitializeDynamoDBClient()
    {
        var config = new AmazonDynamoDBConfig
        {
            RegionEndpoint = RegionEndpoint.USWest1
        };
        client = new AmazonDynamoDBClient(AccessKeyId, SecretAccessKey, config);
    }

    private static async Task CreateTableIfNotExistsAsync()
    {
        try
        {
            await client.DescribeTableAsync(TableName);
        }
        catch (ResourceNotFoundException)
        {
            var request = new CreateTableRequest
            {
                TableName = TableName,
                AttributeDefinitions = new List
                {
                    new AttributeDefinition { AttributeName = "Key", AttributeType = "S" }
                },
                KeySchema = new List
                {
                    new KeySchemaElement { AttributeName = "Key", KeyType = "HASH" }
                },
                ProvisionedThroughput = new ProvisionedThroughput
                {
                    ReadCapacityUnits = 5,
                    WriteCapacityUnits = 5
                }
            };

            await client.CreateTableAsync(request);
            await WaitForTableToBeReadyAsync();
        }
    }

    private static async Task WaitForTableToBeReadyAsync()
    {
        bool isTableReady = false;
        while (!isTableReady)
        {
            var response = await client.DescribeTableAsync(TableName);
            isTableReady = response.Table.TableStatus == TableStatus.ACTIVE;
            if (!isTableReady) await Task.Delay(1000);
        }
    }

    private static async Task AddKeyValuePair(string key, string value)
    {
        var request = new PutItemRequest
        {
            TableName = TableName,
            Item = new Dictionary
            {
                { "Key", new AttributeValue { S = key } },
                { "Value", new AttributeValue { S = value } }
            }
        };

        await client.PutItemAsync(request);
    }

    private static async Task AddKeyValuePair()
    {
        Console.Write("Enter key: ");
        string key = Console.ReadLine();
        Console.Write("Enter value: ");
        string value = Console.ReadLine();

        var request = new PutItemRequest
        {
            TableName = TableName,
            Item = new Dictionary
            {
                { "Key", new AttributeValue { S = key } },
                { "Value", new AttributeValue { S = value } }
            }
        };

        await client.PutItemAsync(request);
        Console.WriteLine("Key-value pair added successfully.");
    }

    private static async Task GetValueByKey()
    {
        Console.Write("Enter key to retrieve: ");
        string key = Console.ReadLine();

        var request = new GetItemRequest
        {
            TableName = TableName,
            Key = new Dictionary
            {
                { "Key", new AttributeValue { S = key } }
            }
        };

        var response = await client.GetItemAsync(request);

        if (response.Item.ContainsKey("Value"))
        {
            Console.WriteLine($"Value: {response.Item["Value"].S}");
        }
        else
        {
            Console.WriteLine("Key not found.");
        }
    }
}

Comments

Popular posts from this blog

Advent of Code - Day 6, 2024: BFS and FSM

Golang vs. C#: performance characteristics (simple case study)

Advent of Code - Day 7, 2024: Backtracking and Eval