diff --git a/.vs/Ch-Ch-Ch-Changes/v16/.suo b/.vs/Ch-Ch-Ch-Changes/v16/.suo index cee2b4f..3a11a92 100644 Binary files a/.vs/Ch-Ch-Ch-Changes/v16/.suo and b/.vs/Ch-Ch-Ch-Changes/v16/.suo differ diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json index 25152f5..2b488d0 100644 --- a/.vs/VSWorkspaceState.json +++ b/.vs/VSWorkspaceState.json @@ -1,8 +1,7 @@ { "ExpandedNodes": [ "", - "\\Demos", - "\\Demos\\Common" + "\\Demos" ], "SelectedNode": "\\Demos\\Ch-ch-ch-changes.sln", "PreviewInSolutionExplorer": false diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index 45c28ba..df5216f 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/Ch-ch-ch-changes - Tracing Changes in Azure Cosmos DB.pptx b/Ch-ch-ch-changes - Tracing Changes in Azure Cosmos DB.pptx index 21e752d..fa92515 100644 Binary files a/Ch-ch-ch-changes - Tracing Changes in Azure Cosmos DB.pptx and b/Ch-ch-ch-changes - Tracing Changes in Azure Cosmos DB.pptx differ diff --git a/Demos/Archive Data/ArchiveData-Function/Properties/launchSettings.json b/Demos/Archive Data/ArchiveData-Function/Properties/launchSettings.json new file mode 100644 index 0000000..e5bbd1a --- /dev/null +++ b/Demos/Archive Data/ArchiveData-Function/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ArchiveData-Function": { + "commandName": "Project", + "commandLineArgs": "host start --pause-on-error --port 7072" + } + } +} \ No newline at end of file diff --git a/Demos/Ch-ch-ch-changes.sln b/Demos/Ch-ch-ch-changes.sln index c1191ab..da13a00 100644 --- a/Demos/Ch-ch-ch-changes.sln +++ b/Demos/Ch-ch-ch-changes.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30524.135 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Archive Data", "Archive Data", "{DDD1150F-EB5F-4D40-90AB-86810CFB1D95}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{8716AE2A-4518-4E42-96ED-34255409A56E}" ProjectSection(SolutionItems) = preProject Data\CPL19.csv = Data\CPL19.csv @@ -14,28 +12,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{8716AE2A-4 Data\QuestionInteractions.csv = Data\QuestionInteractions.csv EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Denormalize Data", "Denormalize Data", "{1B8C4C5F-51EB-4EF6-9735-E6AF5A1740BE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Replicating Data", "Replicating Data", "{94E11704-B8FE-4EDD-9168-A3B2AD601C2E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Event-Driven Architecture", "Event-Driven Architecture", "{98319DFD-EA37-4997-BB20-23B840572219}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQL Scripts", "SQL Scripts", "{DDFBC51A-02F2-4B31-A0B5-8700A57DDA97}" ProjectSection(SolutionItems) = preProject SQL Scripts\GetMetadata.sql = SQL Scripts\GetMetadata.sql SQL Scripts\GetSessionDetails.sql = SQL Scripts\GetSessionDetails.sql EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DenormalizeData-Console", "Denormalize Data\DenormalizeData-Console\DenormalizeData-Console.csproj", "{B7515995-F5CC-490F-A5AC-0DBBC0A70C5B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DenormalizeData-Function", "Denormalize Data\DenormalizeData-Function\DenormalizeData-Function.csproj", "{E3A1FA9C-AA31-438B-8B96-8DBC71011064}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchiveData-Console", "Archive Data\ArchiveData-Console\ArchiveData-Console.csproj", "{BA8C8820-34DA-45EE-8F1A-4973A49A5289}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchiveData-Function", "Archive Data\ArchiveData-Function\ArchiveData-Function.csproj", "{5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventDrivenArchitecture-Console", "Event-Driven Architecture\EventDrivenArchitecture-Console\EventDrivenArchitecture-Console.csproj", "{400D9C3B-88DB-49F8-AB68-75AD4AA9920F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventDrivenArchitecture-Function-Inventory", "Event-Driven Architecture\EventDrivenArchitecture-Function-Inventory\EventDrivenArchitecture-Function-Inventory.csproj", "{24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventDrivenArchitecture-Function-Notification", "Event-Driven Architecture\EventDrivenArchitecture-Function-Notification\EventDrivenArchitecture-Function-Notification.csproj", "{69A276BF-228B-4F1F-8EE8-4E7FA38B5076}" @@ -44,36 +30,26 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventDrivenArchitecture-Fun EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "Common\Common.csproj", "{4FD9813D-67B9-4287-A746-35B282351217}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReplicatingData-Console", "Replicating Data\ReplicatingData-Console\ReplicatingData-Console.csproj", "{62A39531-2697-41FB-BBFE-AAC54E9C4B4E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReplicatingData-Function", "Replicating Data\ReplicatingData-Function\ReplicatingData-Function.csproj", "{D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demonstrator", "Demonstrator\Demonstrator.csproj", "{864C947D-FEA3-4555-8614-A605C3575DC8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Functions", "Functions", "{47234F40-50A8-4366-8818-B2DCE4241F1C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B7515995-F5CC-490F-A5AC-0DBBC0A70C5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7515995-F5CC-490F-A5AC-0DBBC0A70C5B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7515995-F5CC-490F-A5AC-0DBBC0A70C5B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7515995-F5CC-490F-A5AC-0DBBC0A70C5B}.Release|Any CPU.Build.0 = Release|Any CPU {E3A1FA9C-AA31-438B-8B96-8DBC71011064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E3A1FA9C-AA31-438B-8B96-8DBC71011064}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3A1FA9C-AA31-438B-8B96-8DBC71011064}.Release|Any CPU.ActiveCfg = Release|Any CPU {E3A1FA9C-AA31-438B-8B96-8DBC71011064}.Release|Any CPU.Build.0 = Release|Any CPU - {BA8C8820-34DA-45EE-8F1A-4973A49A5289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA8C8820-34DA-45EE-8F1A-4973A49A5289}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA8C8820-34DA-45EE-8F1A-4973A49A5289}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA8C8820-34DA-45EE-8F1A-4973A49A5289}.Release|Any CPU.Build.0 = Release|Any CPU {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF}.Debug|Any CPU.Build.0 = Debug|Any CPU {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF}.Release|Any CPU.ActiveCfg = Release|Any CPU {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF}.Release|Any CPU.Build.0 = Release|Any CPU - {400D9C3B-88DB-49F8-AB68-75AD4AA9920F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {400D9C3B-88DB-49F8-AB68-75AD4AA9920F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {400D9C3B-88DB-49F8-AB68-75AD4AA9920F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {400D9C3B-88DB-49F8-AB68-75AD4AA9920F}.Release|Any CPU.Build.0 = Release|Any CPU {24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -90,29 +66,25 @@ Global {4FD9813D-67B9-4287-A746-35B282351217}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FD9813D-67B9-4287-A746-35B282351217}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FD9813D-67B9-4287-A746-35B282351217}.Release|Any CPU.Build.0 = Release|Any CPU - {62A39531-2697-41FB-BBFE-AAC54E9C4B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {62A39531-2697-41FB-BBFE-AAC54E9C4B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {62A39531-2697-41FB-BBFE-AAC54E9C4B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {62A39531-2697-41FB-BBFE-AAC54E9C4B4E}.Release|Any CPU.Build.0 = Release|Any CPU {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6}.Release|Any CPU.Build.0 = Release|Any CPU + {864C947D-FEA3-4555-8614-A605C3575DC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {864C947D-FEA3-4555-8614-A605C3575DC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {864C947D-FEA3-4555-8614-A605C3575DC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {864C947D-FEA3-4555-8614-A605C3575DC8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {B7515995-F5CC-490F-A5AC-0DBBC0A70C5B} = {1B8C4C5F-51EB-4EF6-9735-E6AF5A1740BE} - {E3A1FA9C-AA31-438B-8B96-8DBC71011064} = {1B8C4C5F-51EB-4EF6-9735-E6AF5A1740BE} - {BA8C8820-34DA-45EE-8F1A-4973A49A5289} = {DDD1150F-EB5F-4D40-90AB-86810CFB1D95} - {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF} = {DDD1150F-EB5F-4D40-90AB-86810CFB1D95} - {400D9C3B-88DB-49F8-AB68-75AD4AA9920F} = {98319DFD-EA37-4997-BB20-23B840572219} - {24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC} = {98319DFD-EA37-4997-BB20-23B840572219} - {69A276BF-228B-4F1F-8EE8-4E7FA38B5076} = {98319DFD-EA37-4997-BB20-23B840572219} - {565F0E7B-DC6C-45B6-9025-DAE3128DD2EA} = {98319DFD-EA37-4997-BB20-23B840572219} - {62A39531-2697-41FB-BBFE-AAC54E9C4B4E} = {94E11704-B8FE-4EDD-9168-A3B2AD601C2E} - {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6} = {94E11704-B8FE-4EDD-9168-A3B2AD601C2E} + {E3A1FA9C-AA31-438B-8B96-8DBC71011064} = {47234F40-50A8-4366-8818-B2DCE4241F1C} + {5192D72A-4BB7-4035-B7C0-CA8A4DBCFBFF} = {47234F40-50A8-4366-8818-B2DCE4241F1C} + {24A4F97F-6C0D-458D-AFDA-FCB38AD08FBC} = {47234F40-50A8-4366-8818-B2DCE4241F1C} + {69A276BF-228B-4F1F-8EE8-4E7FA38B5076} = {47234F40-50A8-4366-8818-B2DCE4241F1C} + {565F0E7B-DC6C-45B6-9025-DAE3128DD2EA} = {47234F40-50A8-4366-8818-B2DCE4241F1C} + {D4C35F1A-CD1A-4542-B5D5-F4C6DB4760B6} = {47234F40-50A8-4366-8818-B2DCE4241F1C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1B250357-A6D7-4256-B401-B5E4B604343B} diff --git a/Demos/Demonstrator/ArchivalDemo.cs b/Demos/Demonstrator/ArchivalDemo.cs new file mode 100644 index 0000000..9cc1ed2 --- /dev/null +++ b/Demos/Demonstrator/ArchivalDemo.cs @@ -0,0 +1,89 @@ +using Azure.Cosmos; +using ShellProgressBar; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using TaleLearnCode.ChChChChanges.Common; + +namespace TaleLearnCode.ChChChChanges.Demonstrator +{ + + public class ArchivalDemo + { + + private readonly CosmosContainer _container; + + private ArchivalDemo(CosmosClient cosmosClient) + { + _container = cosmosClient + .GetDatabase(Settings.MoveDataDatabasebaseName) + .GetContainer(Settings.ArchivalContainerName); + } + + public static async Task ExecuteAsync(CosmosClient cosmosClient) + { + await new ArchivalDemo(cosmosClient).ExecuteAsync(); + } + + private async Task ExecuteAsync() + { + WelcomeUser(); + await AddDataToCosmosAsync(GetQuestionInteractions()); + } + + private void WelcomeUser() + { + Console.Clear(); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(@" _____ .__ .__ .__ "); + Console.WriteLine(@" / _ \_______ ____ | |__ |__|__ _______ | | "); + Console.WriteLine(@" / /_\ \_ __ \_/ ___\| | \| \ \/ /\__ \ | | "); + Console.WriteLine(@"/ | \ | \/\ \___| Y \ |\ / / __ \| |__"); + Console.WriteLine(@"\____|__ /__| \___ >___| /__| \_/ (____ /____/"); + Console.WriteLine(@" \/ \/ \/ \/ "); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.White; + } + + private List GetQuestionInteractions() + { + Console.WriteLine(); + Console.WriteLine(); + return QuestionInteraction.GetListOfInteractions($"{Settings.DataFolderPath}QuestionInteractions.csv"); + } + + private async Task AddDataToCosmosAsync(List questionInteractions) + { + + Console.WriteLine(); + Console.WriteLine("Press any key to start the writing data to Cosmos..."); + Console.ReadKey(); + + Console.WriteLine(); + Console.WriteLine(); + using var progressBar = new ProgressBar(questionInteractions.Count, "Connecting to database"); + + int index = 0; + do + { + while (!Console.KeyAvailable && index < questionInteractions.Count) + { + progressBar.Tick($"Writing interaction {index + 1:n0} of {questionInteractions.Count:n0}"); + await _container.CreateItemAsync(questionInteractions[index]); + var delay = questionInteractions[index + 1].InteractionDateTime.Subtract(questionInteractions[index].InteractionDateTime); + await Task.Delay(Convert.ToInt32(delay.TotalMilliseconds)); + index++; + } + if (index >= questionInteractions.Count - 1) break; + } while (Console.ReadKey(true).Key != ConsoleKey.Escape); + + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine($"Finished writing data to the {Settings.ArchivalContainerName} container"); + + } + + } + +} \ No newline at end of file diff --git a/Demos/Demonstrator/DemoOption.cs b/Demos/Demonstrator/DemoOption.cs new file mode 100644 index 0000000..408ed9e --- /dev/null +++ b/Demos/Demonstrator/DemoOption.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Demonstrator +{ + + public enum DemoOption + { + Exit = 0, + ArchivingData = 1, + ReplicatingContainers = 2, + DenormalizingData = 3, + EventDrivenArchitecture = 4, + RealTimeReporting = 5 + } + +} \ No newline at end of file diff --git a/Demos/Demonstrator/Demonstrator.csproj b/Demos/Demonstrator/Demonstrator.csproj new file mode 100644 index 0000000..cec6c9c --- /dev/null +++ b/Demos/Demonstrator/Demonstrator.csproj @@ -0,0 +1,19 @@ + + + + Exe + netcoreapp3.1 + TaleLearnCode.ChChChChanges.Demonstrator + TaleLearnCode.ChChChChanges.Demonstrator + + + + + + + + + + + + diff --git a/Demos/Demonstrator/DenormalizeDemo.cs b/Demos/Demonstrator/DenormalizeDemo.cs new file mode 100644 index 0000000..14959b4 --- /dev/null +++ b/Demos/Demonstrator/DenormalizeDemo.cs @@ -0,0 +1,191 @@ +using Azure.Cosmos; +using Microsoft.VisualBasic.FileIO; +using ShellProgressBar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using TaleLearnCode.ChChChChanges.Common; + +namespace TaleLearnCode.ChChChChanges.Demonstrator +{ + + public class DenormalizeDemo + { + + private readonly CosmosDatabase _database; + + private DenormalizeDemo(CosmosClient cosmosClient) + { + _database = cosmosClient.GetDatabase(Settings.ShindigManagerDatabaseName); + } + + public static async Task ExecuteAsync(CosmosClient cosmosClient) + { + await new DenormalizeDemo(cosmosClient).ExecuteAsync(); + } + + private async Task ExecuteAsync() + { + var execute = true; + while (execute) + { + WelcomeUser(); + Console.WriteLine("Select an option:"); + Console.WriteLine("\tUpload [P]resentations"); + Console.WriteLine("\tUpload [M]etedata"); + Console.WriteLine("\tE[x]it"); + var cki = Console.ReadKey(); + if (cki.Key == ConsoleKey.P) await AddPresentationsToCosmosAsync(); + if (cki.Key == ConsoleKey.M) await AddMetadataToCosmosAsync(); + if (cki.Key == ConsoleKey.X) execute = false; + } + } + + private static void WelcomeUser() + { + Console.Clear(); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(@"________ .__ .__ "); + Console.WriteLine(@"\______ \ ____ ____ ___________ _____ _____ | | |__|_______ ____ "); + Console.WriteLine(@" | | \_/ __ \ / \ / _ \_ __ \/ \\__ \ | | | \___ // __ \ "); + Console.WriteLine(@" | ` \ ___/| | ( <_> ) | \/ Y Y \/ __ \| |_| |/ /\ ___/ "); + Console.WriteLine(@"/_______ /\___ >___| /\____/|__| |__|_| (____ /____/__/_____ \\___ >"); + Console.WriteLine(@" \/ \/ \/ \/ \/ \/ \/ "); Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.White; + } + + private (List Metadata, List Speakers) GetMetadata() + { + + var metadata = new List(); + var speakers = new List(); + + using var parser = new TextFieldParser($"{Settings.DataFolderPath}Metadata.csv"); + parser.TextFieldType = FieldType.Delimited; + parser.SetDelimiters(","); + while (!parser.EndOfData) + { + string[] fields = parser.ReadFields(); + if (fields[MetadataFields.Type] != "speaker") + metadata.Add( + new Metadata( + fields[MetadataFields.Type], + fields[MetadataFields.Id], + fields[MetadataFields.Name])); + else + speakers.Add( + new Speaker( + fields[MetadataFields.Id], + fields[MetadataFields.FirstName], + fields[MetadataFields.LastName])); + } + + return (metadata, speakers); + + } + + private async Task AddMetadataToCosmosAsync() + { + + Console.WriteLine(); + Console.WriteLine("Retrieving the metadata..."); + var metadata = GetMetadata(); + + Console.WriteLine(); + using var progressBar = new ProgressBar(metadata.Metadata.Count + metadata.Speakers.Count, "Connecting to the Cosmos DB container"); + int counter = 0; + + CosmosContainer container = _database.GetContainer(Settings.MetadataContainerName); + + foreach (var item in metadata.Metadata) + { + counter++; + await container.CreateItemAsync(item); + progressBar.Tick($"Writing metadata item {counter} of {metadata.Metadata.Count + metadata.Speakers.Count}"); + } + + foreach (var speaker in metadata.Speakers) + { + counter++; + await container.CreateItemAsync(speaker); + progressBar.Tick($"Writing metadata item {counter} of {metadata.Metadata.Count + metadata.Speakers.Count}"); + } + + } + + private async Task AddPresentationsToCosmosAsync() + { + + Console.WriteLine(); + Console.WriteLine("Retrieving the presentations..."); + var presentations = GetAllPresentations(); + + Console.WriteLine(); + using var progressBar = new ProgressBar(presentations.Count, "Connecting to the Cosmos DB container"); + int counter = 0; + + CosmosContainer container = _database.GetContainer(Settings.PresentationsContainerName); + + foreach (var presentation in presentations) + { + counter++; + await container.CreateItemAsync(presentation); + progressBar.Tick($"Writing presentation {counter} of {presentations.Count}"); + } + + } + + private List GetAllPresentations() + { + var presentations = new List(); + presentations.AddRange(GetEventPresentations("CPL19")); + presentations.AddRange(GetEventPresentations("CPL20")); + return presentations; + } + + private List GetEventPresentations(string eventId) + { + + var presentations = new Dictionary(); + + using var parser = new TextFieldParser($"{Settings.DataFolderPath}{eventId}.csv"); + parser.TextFieldType = FieldType.Delimited; + parser.SetDelimiters(","); + while (!parser.EndOfData) + { + string[] fields = parser.ReadFields(); + + if (presentations.ContainsKey(fields[PresentationFields.Id])) + { + + if (presentations[fields[PresentationFields.Id]].Speakers.FindIndex(x => x.Id == fields[PresentationFields.SpeakerId]) == -1) + presentations[fields[PresentationFields.Id]].Speakers.Add( + new Speaker( + fields[PresentationFields.SpeakerId], + fields[PresentationFields.SpeakerFirstName], + fields[PresentationFields.SpeakerLastName])); + + if (presentations[fields[PresentationFields.Id]].Topics.FindIndex(x => x.Id == fields[PresentationFields.TopicId]) == -1) + presentations[fields[PresentationFields.Id]].Topics.Add( + Metadata.TopicFactory(fields[PresentationFields.TopicId], + fields[PresentationFields.TopicName])); + + if (presentations[fields[PresentationFields.Id]].Tags.FindIndex(x => x.Id == fields[PresentationFields.TagId]) == -1) + presentations[fields[PresentationFields.Id]].Tags.Add( + Metadata.TagFactory(fields[PresentationFields.TagId], + fields[PresentationFields.TagName])); + + } + else + presentations.Add(fields[PresentationFields.Id], new Presentation(fields)); + } + + return presentations.Values.ToList(); + + } + + } + +} \ No newline at end of file diff --git a/Demos/Demonstrator/EventDrivenArchitectureDemo.cs b/Demos/Demonstrator/EventDrivenArchitectureDemo.cs new file mode 100644 index 0000000..42ff262 --- /dev/null +++ b/Demos/Demonstrator/EventDrivenArchitectureDemo.cs @@ -0,0 +1,158 @@ +using Azure.Cosmos; +using Microsoft.VisualBasic.FileIO; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using TaleLearnCode.ChChChChanges.Common; + +namespace TaleLearnCode.ChChChChanges.Demonstrator +{ + + public class EventDrivenArchitectureDemo + { + + private readonly CosmosContainer _container; + private List _fakeNames = new List(); + private List _products = new List(); + + private EventDrivenArchitectureDemo(CosmosClient cosmosClient) + { + _container = cosmosClient + .GetDatabase(Settings.OrderManagementDatabaseName) + .GetContainer(Settings.OrdersContainerName); + _fakeNames = GetFakeNames(); + _products = GetProducts(); + } + + public static async Task ExecuteAsync(CosmosClient cosmosClient) + { + await new EventDrivenArchitectureDemo(cosmosClient).ExecuteAsync(); + } + + private async Task ExecuteAsync() + { + WelcomeUser(); + do + { + while (!Console.KeyAvailable) + { + var order = GetOrder(); + await _container.CreateItemAsync(order); + Console.WriteLine($"Saved order #{order.Id}"); + await Task.Delay(500); + } + } while (Console.ReadKey(true).Key != ConsoleKey.Escape); + } + + private static void WelcomeUser() + { + Console.Clear(); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(@"___________________ _____ "); + Console.WriteLine(@"\_ _____/\______ \ / _ \ "); + Console.WriteLine(@" | __)_ | | \ / /_\ \ "); + Console.WriteLine(@" | \ | ` \/ | \"); + Console.WriteLine(@"/_______ //_______ /\____|__ /"); + Console.WriteLine(@" \/ \/ \/ "); + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(); + } + + private List GetFakeNames() + { + + var returnValue = new List(); + + Console.WriteLine("Generating fake names for the demo..."); + + using var parser = new TextFieldParser($"{Settings.DataFolderPath}FakeNames.csv"); + parser.TextFieldType = FieldType.Delimited; + parser.SetDelimiters(","); + while (!parser.EndOfData) + { + string[] fields = parser.ReadFields(); + returnValue.Add(new FakeName() + { + FirstName = fields[FakeNameFields.GivenName], + LastName = fields[FakeNameFields.Surname], + StreetAddress = fields[FakeNameFields.StreetAddress], + City = fields[FakeNameFields.City], + State = fields[FakeNameFields.State], + PostalCode = fields[FakeNameFields.ZipCode], + Country = fields[FakeNameFields.Country], + EmailAddress = fields[FakeNameFields.EmailAddress], + UserName = fields[FakeNameFields.UserName] + }); + } + + return returnValue; + } + + private List GetProducts() + { + var returnValue = new List(); + Console.WriteLine("Generating fake products for the demo..."); + returnValue.Add(new Product("10267", "Creator Gingerbread House", 99.99m)); + returnValue.Add(new Product("10255", "Creator Assembly Square", 279.99m)); + returnValue.Add(new Product("10261", "Creator Roller Coaster", 379.99m)); + returnValue.Add(new Product("10256", "Crator Taj Mahal", 369.99m)); + returnValue.Add(new Product("75192", "Millennium Falcon", 799.99m)); + returnValue.Add(new Product("71040", "The Disney Castle", 349.99m)); + returnValue.Add(new Product("75290", "Mos Eisley Cantina", 349.99m)); + returnValue.Add(new Product("76161", "1989 Batwing", 199.99m)); + returnValue.Add(new Product("21323", "Ideas Grand Piano", 349.99m)); + returnValue.Add(new Product("10270", "Creator Bookshop", 179.99m)); + returnValue.Add(new Product("10264", "Creator Corner Garage", 199.99m)); + returnValue.Add(new Product("10275", "Elf Club House", 9.99m)); + returnValue.Add(new Product("10273", "Creator Haunted House", 249.99m)); + returnValue.Add(new Product("10262", "Creator James Bond™ Aston Martin DB5", 149.99m)); + returnValue.Add(new Product("75288", "AT-AT", 159.99m)); + returnValue.Add(new Product("75271", "Luke Skywalker's Landspeeder™", 29.99m)); + returnValue.Add(new Product("75292", "The Razor Crest", 129.99m)); + returnValue.Add(new Product("75275", "A-wing Starfighter™", 199.99m)); + returnValue.Add(new Product("21317", "Ideas Steamboat Willie", 89.99m)); + returnValue.Add(new Product("21316", "Ideas The Flintstones", 59.99m)); + returnValue.Add(new Product("10260", "Creator Downtown Diner", 169.99m)); + returnValue.Add(new Product("10255", "Creator Assembly Square", 279.99m)); + returnValue.Add(new Product("21034", "Architecture London", 39.99m)); + returnValue.Add(new Product("21047", "Architecture Las Vegas", 39.99m)); + returnValue.Add(new Product("21043", "Architecture San Francisco", 49.99m)); + returnValue.Add(new Product("21051", "Architecture Tokyo", 59.99m)); + returnValue.Add(new Product("21028", "Architecture New York City", 59.99m)); + returnValue.Add(new Product("21052", "Architecture Dubai", 59.99m)); + returnValue.Add(new Product("21045", "Architecture Trafalgar Square", 79.99m)); + returnValue.Add(new Product("21042", "Architecture Statue of Liberty", 119.99m)); + returnValue.Add(new Product("21046", "Architecture Empire State Building", 129.99m)); + returnValue.Add(new Product("21054", "Architecture The White House", 99.99m)); + + return returnValue; + } + + private Order GetOrder() + { + var rand = new Random(); + + var customer = _fakeNames[rand.Next(0, _fakeNames.Count)]; + var order = new Order() + { + UserName = customer.UserName, + EmailAddress = customer.EmailAddress, + ShippingAddress = new PostalAddress(customer.FirstName, customer.LastName, customer.StreetAddress, customer.State, customer.PostalCode, customer.Country), + OrderDateTime = DateTime.UtcNow + }; + + var numberOfItems = rand.Next(1, 10); + for (int i = 1; i <= numberOfItems; i++) + { + var product = _products[rand.Next(0, _products.Count)]; + order.OrderItems.Add(new OrderItem(product, rand.Next(1, 3))); + } + + return order; + + } + + } + +} \ No newline at end of file diff --git a/Demos/Demonstrator/Program.cs b/Demos/Demonstrator/Program.cs new file mode 100644 index 0000000..45ea4cb --- /dev/null +++ b/Demos/Demonstrator/Program.cs @@ -0,0 +1,134 @@ +using Azure.Cosmos; +using System; +using System.Linq; +using System.Threading.Tasks; +using TaleLearnCode.ChChChChanges.Common; +using TaleLearnCode.ChChChChanges.Demonstrator; + +namespace Demonstrator +{ + class Program + { + + static async Task Main(string[] args) + { + + //LoopTest(); + + CosmosClient cosmosClient = new CosmosClient(Settings.CosmosConnectionString); + + var exit = false; + while (!exit) + { + switch (ProvideDemoOptions()) + { + case DemoOption.ArchivingData: + await ArchivalDemo.ExecuteAsync(cosmosClient); + break; + case DemoOption.DenormalizingData: + await DenormalizeDemo.ExecuteAsync(cosmosClient); + break; + case DemoOption.EventDrivenArchitecture: + break; + case DemoOption.Exit: + exit = true; + break; + case DemoOption.RealTimeReporting: + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("This demo is not ready yet. Press any key to continue..."); + Console.Beep(); + Console.ReadKey(); + break; + case DemoOption.ReplicatingContainers: + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("There is no dedicated demo; perform the demo from the Azure Portal. Press any key to continue..."); + Console.Beep(); + Console.ReadKey(); + break; + } + } + + + } + + private static DemoOption ProvideDemoOptions() + { + int returnValue = -1; + + int minDemoOptionValue = (int)Enum.GetValues(typeof(DemoOption)).Cast().First(); + int maxDemoOptionValue = (int)Enum.GetValues(typeof(DemoOption)).Cast().Last(); + while (returnValue < minDemoOptionValue || returnValue > maxDemoOptionValue) + { + Console.Clear(); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(@"_________ .__ ___________ .___"); + Console.WriteLine(@"\_ ___ \| |__ _____ ____ ____ ____ \_ _____/___ ____ __| _/"); + Console.WriteLine(@"/ \ \/| | \\__ \ / \ / ___\_/ __ \ | __)/ __ \_/ __ \ / __ | "); + Console.WriteLine(@"\ \___| Y \/ __ \| | \/ /_/ > ___/ | \\ ___/\ ___// /_/ | "); + Console.WriteLine(@" \______ /___| (____ /___| /\___ / \___ > \___ / \___ >\___ >____ | "); + Console.WriteLine(@" \/ \/ \/ \//_____/ \/ \/ \/ \/ \/ "); Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine("Choose the demo to run:"); + Console.WriteLine("\t [1] Archiving Data"); + Console.WriteLine("\t [2] Replicating Containers"); + Console.WriteLine("\t [3] Denormalizing Data"); + Console.WriteLine("\t [4] Event-Driven Architecture"); + Console.WriteLine("\t [5] Real-Time Reporting"); + Console.WriteLine("\t[ESC] Exit demo"); + var keyPress = Console.ReadKey(true); + switch (keyPress.Key) + { + case ConsoleKey.D1: + case ConsoleKey.NumPad1: + returnValue = (int)DemoOption.ArchivingData; + break; + case ConsoleKey.D2: + case ConsoleKey.NumPad2: + returnValue = (int)DemoOption.ReplicatingContainers; + break; + case ConsoleKey.D3: + case ConsoleKey.NumPad3: + returnValue = (int)DemoOption.DenormalizingData; + break; + case ConsoleKey.D4: + case ConsoleKey.NumPad4: + returnValue = (int)DemoOption.EventDrivenArchitecture; + break; + case ConsoleKey.D5: + case ConsoleKey.NumPad5: + returnValue = (int)DemoOption.RealTimeReporting; + break; + case ConsoleKey.Escape: + returnValue = (int)DemoOption.Exit; + break; + } + } + + return (DemoOption)returnValue; + + } + + private static void LoopTest() + { + int counter = 0; + Console.WriteLine("Press ESC to stop"); + do + { + while (!Console.KeyAvailable && counter < 100000) + { + counter++; + Console.WriteLine(counter); + } + if (counter >= 100000) break; + } while (Console.ReadKey(true).Key != ConsoleKey.Escape); + + Console.Beep(); + Console.WriteLine("Done"); + } + + } +} \ No newline at end of file diff --git a/Demos/Denormalize Data/DenormalizeData-Function/Properties/launchSettings.json b/Demos/Denormalize Data/DenormalizeData-Function/Properties/launchSettings.json new file mode 100644 index 0000000..d572c92 --- /dev/null +++ b/Demos/Denormalize Data/DenormalizeData-Function/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "DenormalizeData-Function": { + "commandName": "Project", + "commandLineArgs": "host start --pause-on-error --port 7073" + } + } +} \ No newline at end of file diff --git a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Fulfillment/Properties/launchSettings.json b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Fulfillment/Properties/launchSettings.json index 39946c0..3e469d7 100644 --- a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Fulfillment/Properties/launchSettings.json +++ b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Fulfillment/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "EventDriveArchitecture-Function-Fulfillment": { "commandName": "Project", - "commandLineArgs": "host start --pause-on-error --port 7080" + "commandLineArgs": "host start --pause-on-error --port 7075" } } } \ No newline at end of file diff --git a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Inventory/Properties/launchSettings.json b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Inventory/Properties/launchSettings.json index 59d7d42..34e1438 100644 --- a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Inventory/Properties/launchSettings.json +++ b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Inventory/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "EventDrivenArchitecture-Function-Inventory": { "commandName": "Project", - "commandLineArgs": "host start --pause-on-error --port 7081" + "commandLineArgs": "host start --pause-on-error --port 7076" } } } \ No newline at end of file diff --git a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Notification/Properties/launchSettings.json b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Notification/Properties/launchSettings.json index 5d47e8b..95359af 100644 --- a/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Notification/Properties/launchSettings.json +++ b/Demos/Event-Driven Architecture/EventDrivenArchitecture-Function-Notification/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "EventDrivenArchitecture-Function-Notification": { "commandName": "Project", - "commandLineArgs": "host start --pause-on-error --port 7082" + "commandLineArgs": "host start --pause-on-error --port 7077" } } } \ No newline at end of file diff --git a/Demos/Replicating Data/ReplicatingData-Function/Properties/launchSettings.json b/Demos/Replicating Data/ReplicatingData-Function/Properties/launchSettings.json new file mode 100644 index 0000000..30c25c9 --- /dev/null +++ b/Demos/Replicating Data/ReplicatingData-Function/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ReplicatingData-Function": { + "commandName": "Project", + "commandLineArgs": "host start --pause-on-error --port 7074" + } + } +} \ No newline at end of file