Temporary repo to track my changes on LTS functions app porting
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
14 KiB

using Microsoft.Azure.Cosmos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CDP
{
public class GroupsDB
{
private static Lazy<CosmosClient> lazyClient = new Lazy<CosmosClient>(InitializeCosmosClient);
private static CosmosClient cosmosClient => lazyClient.Value;
private static string DatabaseName = "CDP";
private static string ContainerName = "Groups";
private static CosmosClient InitializeCosmosClient()
{
// Perform any initialization here
var uri = "https://cdplite.documents.azure.com:443/";
var authKey = "VPbg8RpzyI3XwhC2o0dIUtYFs33ghxORCqZeNAyg8vg4HWUBjM41BUxP0qLFXEvFh6ewQY1uKv52ACDbsEN1AQ==";
return new CosmosClient(uri, authKey);
}
public static async Task<List<GroupsRecord>> GetUserGroups(string AppKey, string UserId)
{
var results = new List<GroupsRecord>();
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
// Fetch the metadata document for the customer ID
var metadataDocumentId = GetMetaDocumentKey(AppKey, UserId);
MetadataDocumentGroups metadataDocument = null;
try
{
var metadataDocumentResponse =
await container.ReadItemAsync<MetadataDocumentGroups>(metadataDocumentId, new PartitionKey(metadataDocumentId));
metadataDocument = metadataDocumentResponse.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
}
if (metadataDocument == null)
return results;
// Determine the partition keys within the date range
var partitionKeysInDocument = metadataDocument.PartitionKeys;
// Fetch the audit records for each partition key within the date range
foreach (var partitionKey in partitionKeysInDocument)
{
ItemResponse<GroupsDocument> response = await container.ReadItemAsync<GroupsDocument>(partitionKey, new PartitionKey(partitionKey));
if (response == null)
continue;
GroupsDocument t = response.Resource;
results.AddRange(t.Records);
}
return results;
}
public static async Task<bool> RemoveGroup(string appKey, string userId, string groupId)
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
// Fetch the metadata document for the customer ID
var metadataDocumentId = GetMetaDocumentKey(appKey, userId);
MetadataDocumentContact metadataDocument = null;
try
{
var metadataDocumentResponse = await container.ReadItemAsync<MetadataDocumentContact>(metadataDocumentId, new PartitionKey(metadataDocumentId));
metadataDocument = metadataDocumentResponse.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
}
if (metadataDocument == null)
return false;
// Determine the partition keys within the date range
var partitionKeysInDocument = metadataDocument.PartitionKeys;
// Fetch the audit records for each partition key within the date range
foreach (var partitionKey in partitionKeysInDocument)
{
ItemResponse<GroupsDocument> response = await container.ReadItemAsync<GroupsDocument>(partitionKey, new PartitionKey(partitionKey));
if (response == null)
continue;
GroupsDocument t = response.Resource;
var originalCount = t.Records.Count;
t.Records = t.Records.Where(item => item.id != groupId).ToList();
var afterFilterCount = t.Records.Count;
if (originalCount != afterFilterCount)
{
ItemResponse<GroupsDocument> updateResponse = await container.ReplaceItemAsync(
item: t,
id: t.id,
partitionKey: new PartitionKey(partitionKey));
return true;
}
}
return false;
}
public static async Task<bool> AppendGroup(string appKey, string userId, String grpName, string grpDescription, List<ContactRecord> rec)
{
try
{
var metadataDocument = await GetMetadataDocument(appKey, userId);
if (metadataDocument == null)
return false;
string dayKey = metadataDocument.GetLatestKey(appKey, userId);
GroupsDocument al = await GetGroupDocument(dayKey);
if (al == null)
{
al = new GroupsDocument();
al.AppKey = appKey;
al.UserId = userId;
}
GroupsRecord gr = new GroupsRecord(grpName, grpDescription, rec);
al.Records.Add(gr);
await UpdateGroupsDocument(al);
return true;
}
catch (Exception e)
{
return false;
}
}
public static async Task<bool> UpdateGroup(string appKey, string userId, string grpId, string grpName, string grpDescription, List<ContactRecord> contacts)
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
// Fetch the metadata document for the customer ID
var metadataDocumentId = GetMetaDocumentKey(appKey, userId);
MetadataDocumentContact metadataDocument = null;
try
{
var metadataDocumentResponse = await container.ReadItemAsync<MetadataDocumentContact>(metadataDocumentId, new PartitionKey(metadataDocumentId));
metadataDocument = metadataDocumentResponse.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
}
if (metadataDocument == null)
return false;
// Determine the partition keys within the date range
var partitionKeysInDocument = metadataDocument.PartitionKeys;
// Fetch the audit records for each partition key within the date range
foreach (var partitionKey in partitionKeysInDocument)
{
ItemResponse<GroupsDocument> response = await container.ReadItemAsync<GroupsDocument>(partitionKey, new PartitionKey(partitionKey));
if (response == null)
continue;
GroupsDocument t = response.Resource;
bool groupFound = false;
foreach (GroupsRecord gr in t.Records)
{
if (gr.id == grpId)
{
gr.Name = grpName != "" ? grpName : gr.Name;
gr.Description = grpDescription != "" ? grpDescription : gr.Description;
gr.Contacts = contacts;
groupFound = true;
break;
}
}
if (groupFound)
{
ItemResponse<GroupsDocument> updateResponse = await container.ReplaceItemAsync(
item: t,
id: t.id,
partitionKey: new PartitionKey(partitionKey));
return true;
}
}
return false;
}
public static async Task UpdateGroupsDocument(GroupsDocument al)
{
if (al.Records.Count == 0)
return;
List<GroupsDocument> lal = await SplitUserGroups(al);
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
foreach (GroupsDocument ial in lal)
{
ItemResponse<GroupsDocument> r = await container.UpsertItemAsync(ial, new PartitionKey(ial.id));
}
await UpdateMetadata(container, lal);
}
static async Task UpdateMetadata(Container container, List<GroupsDocument> lal)
{
bool update = false;
string pKey = GetMetaDocumentKey(lal[0].AppKey, lal[0].UserId);
MetadataDocument md = null;
try
{
ItemResponse<MetadataDocument> response =
await container.ReadItemAsync<MetadataDocument>(pKey, new PartitionKey(pKey));
md = response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
md = new MetadataDocument()
{
id = GetMetaDocumentKey(lal[0].AppKey, lal[0].UserId),
PartitionKeys = new List<string>()
};
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
return;
}
if (md == null)
{
// Helpers.LogIt("Something ugly happened!");
return;
}
foreach (GroupsDocument log in lal)
{
if (md.PartitionKeys.Contains(log.id))
continue;
md.PartitionKeys.Add(log.id);
update = true;
}
if (update)
{
try
{
ItemResponse<MetadataDocument> r = await container.UpsertItemAsync(md, new PartitionKey(pKey));
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
return;
}
}
}
static async Task<List<GroupsDocument>> SplitUserGroups(GroupsDocument al)
{
List<GroupsDocument> lal = new List<GroupsDocument>();
var sortedRecords = al.Records.OrderBy(record => record.EventTime).ToList();
var currentGroup = new List<GroupsRecord>();
var currentGroupSize = 0;
int MaxDocumentSizeInBytes = 2 * 1024 * 1024; // 2MB
int index = al.Index; // start for index passed in
foreach (var record in sortedRecords)
{
var recordSize = record.CalculateRecordSize();
if (currentGroupSize + recordSize > MaxDocumentSizeInBytes)
{
GroupsDocument i = new GroupsDocument();
i.Index = index++;
i.Records = currentGroup;
i.AppKey = al.AppKey;
i.UserId = al.UserId;
lal.Add(i);
currentGroup = new List<GroupsRecord>();
currentGroupSize = 0;
}
currentGroup.Add(record);
currentGroupSize += recordSize;
}
if (currentGroup.Any())
{
GroupsDocument i = new GroupsDocument();
i.Index = index++;
i.Records = currentGroup;
i.AppKey = al.AppKey;
i.UserId = al.UserId;
lal.Add(i);
}
return lal;
}
public static async Task<GroupsDocument> GetGroupDocument(string key)
{
try
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
ItemResponse<GroupsDocument> response = await container.ReadItemAsync<GroupsDocument>(key, new PartitionKey(key));
if (response == null)
return null;
GroupsDocument t = response.Resource;
return t;
}
catch (Exception e)
{
return null;
}
}
static async Task<MetadataDocumentGroups> GetMetadataDocument(string appKey, string userId)
{
MetadataDocumentGroups md = null;
string pKey = GetMetaDocumentKey(appKey, userId);
string id = GetDocumentId(appKey, userId);
PartitionKey partitionKey = new PartitionKeyBuilder()
.Add(pKey)
.Build();
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
try
{
ItemResponse<MetadataDocumentGroups> response =
await container.ReadItemAsync<MetadataDocumentGroups>(pKey, partitionKey);
md = response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
md = new MetadataDocumentGroups()
{
id = id,
PartitionKeys = new List<string>()
};
}
catch (Exception e)
{
// Helpers.LogIt(e.Message);
return null;
}
if (md == null)
{
// Helpers.LogIt("Something ugly happened!");
return null;
}
return md;
}
static string GetMetaDocumentKey(string appKey, string userId)
{
return $"{appKey}-{userId}-meta";
}
static string GetDocumentId(string appKey, string userId)
{
return $"{appKey}-{userId}";
}
}
}