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
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}";
|
|
}
|
|
}
|
|
}
|