Skip to content

Commit

Permalink
Clean solution commit
Browse files Browse the repository at this point in the history
  • Loading branch information
joelhulen committed Jan 6, 2018
1 parent 7c10068 commit 3b92698
Show file tree
Hide file tree
Showing 22 changed files with 849 additions and 177 deletions.
12 changes: 6 additions & 6 deletions TollBooth.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2003
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TollBooth", "TollBooth\TollBooth.csproj", "{58B34BE7-1F92-45A6-AA28-56E4684640E4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TollBooth", "TollBooth\TollBooth.csproj", "{58B34BE7-1F92-45A6-AA28-56E4684640E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TollBoth_Tests", "TollBoth_Tests\TollBoth_Tests.csproj", "{73589AA0-D7C0-461B-9896-E5F89A359D71}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UploadImages", "UploadImages\UploadImages.csproj", "{A7110625-77CF-45DD-920F-F35E8A4740BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -17,10 +17,10 @@ Global
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58B34BE7-1F92-45A6-AA28-56E4684640E4}.Release|Any CPU.Build.0 = Release|Any CPU
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73589AA0-D7C0-461B-9896-E5F89A359D71}.Release|Any CPU.Build.0 = Release|Any CPU
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7110625-77CF-45DD-920F-F35E8A4740BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
80 changes: 80 additions & 0 deletions TollBooth/DatabaseMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.WebJobs.Host;
using TollBooth.Models;

namespace TollBooth
{
internal class DatabaseMethods
{
private readonly string _endpointUrl = ConfigurationManager.AppSettings["cosmosDBEndPointUrl"];
private readonly string _authorizationKey = ConfigurationManager.AppSettings["cosmosDBAuthorizationKey"];
private readonly string _databaseId = ConfigurationManager.AppSettings["cosmosDBDatabaseId"];
private readonly string _collectionId = ConfigurationManager.AppSettings["cosmosDBCollectionId"];
private readonly TraceWriter _log;
// Reusable instance of DocumentClient which represents the connection to a Cosmos DB endpoint.
private DocumentClient _client;

public DatabaseMethods(TraceWriter log)
{
_log = log;
}

/// <summary>
/// Retrieves all license plate records (documents) that have not yet been exported.
/// </summary>
/// <returns></returns>
public List<LicensePlateDataDocument> GetLicensePlatesToExport()
{
_log.Info("Retrieving license plates to export");
int exportedCount = 0;
var collectionLink = UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId);
List<LicensePlateDataDocument> licensePlates;

using (_client = new DocumentClient(new Uri(_endpointUrl), _authorizationKey))
{
// MaxItemCount value tells the document query to retrieve 100 documents at a time until all are returned.
// TODO 5: Retrieve a List of LicensePlateDataDocument objects from the collectionLink where the exported value is false.
// COMPLETE: licensePlates = _client.CreateDocumentQuery ...
// TODO 6: Remove the line below.
licensePlates = new List<LicensePlateDataDocument>();
}

exportedCount = licensePlates.Count();
_log.Info($"{exportedCount} license plates found that are ready for export");
return licensePlates;
}

/// <summary>
/// Updates license plate records (documents) as exported. Call after successfully
/// exporting the passed in license plates.
/// In a production environment, it would be best to create a stored procedure that
/// bulk updates the set of documents, vastly reducing the number of transactions.
/// </summary>
/// <param name="licensePlates"></param>
/// <returns></returns>
public async Task MarkLicensePlatesAsExported(IEnumerable<LicensePlateDataDocument> licensePlates)
{
_log.Info("Updating license plate documents exported values to true");
var collectionLink = UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId);

using (_client = new DocumentClient(new Uri(_endpointUrl), _authorizationKey))
{
foreach (var licensePlate in licensePlates)
{
licensePlate.exported = true;
var response = await _client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(_databaseId, _collectionId, licensePlate.Id), licensePlate);

var updated = response.Resource;
//_log.Info($"Exported value of updated document: {updated.GetPropertyValue<bool>("exported")}");
}
}
}

}
}
50 changes: 50 additions & 0 deletions TollBooth/ExportLicensePlates.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

namespace TollBooth
{
public static class ExportLicensePlates
{
[FunctionName("ExportLicensePlates")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
int exportedCount = 0;
log.Info("Finding license plate data to export");

var databaseMethods = new DatabaseMethods(log);
var licensePlates = databaseMethods.GetLicensePlatesToExport();
if (licensePlates.Any())
{
log.Info($"Retrieved {licensePlates.Count} license plates");
var fileMethods = new FileMethods(log);
var uploaded = await fileMethods.GenerateAndSaveCsv(licensePlates);
if (uploaded)
{
await databaseMethods.MarkLicensePlatesAsExported(licensePlates);
exportedCount = licensePlates.Count;
log.Info("Finished updating the license plates");
}
else
{
log.Info(
"Export file could not be uploaded. Skipping database update that marks the documents as exported.");
}

log.Info($"Exported {exportedCount} license plates");
}
else
{
log.Info("No license plates to export");
}

return exportedCount == 0
? req.CreateResponse(HttpStatusCode.NoContent)
: req.CreateResponse(HttpStatusCode.OK, $"Exported {exportedCount} license plates");
}
}
}
91 changes: 91 additions & 0 deletions TollBooth/FileMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CsvHelper;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using TollBooth.Models;

namespace TollBooth
{
internal class FileMethods
{
private readonly CloudBlobClient _blobClient;
private readonly string _containerName = ConfigurationManager.AppSettings["exportCsvContainerName"];
private readonly string _blobStorageConnection = ConfigurationManager.AppSettings["blobStorageConnection"];
private readonly TraceWriter _log;

public FileMethods(TraceWriter log)
{
_log = log;
// Retrieve storage account information from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_blobStorageConnection);

// Create a blob client for interacting with the blob service.
_blobClient = storageAccount.CreateCloudBlobClient();
}

public async Task<bool> GenerateAndSaveCsv(IEnumerable<LicensePlateDataDocument> licensePlates)
{
var successful = false;

_log.Info("Generating CSV file");
string blobName = $"{DateTime.UtcNow.ToString("s")}.csv";

using (var stream = new MemoryStream())
{
using (var textWriter = new StreamWriter(stream))
using (var csv = new CsvWriter(textWriter))
{
csv.Configuration.Delimiter = ",";
csv.WriteRecords(licensePlates.Select(ToLicensePlateData));
await textWriter.FlushAsync();

_log.Info($"Beginning file upload: {blobName}");
try
{
var container = _blobClient.GetContainerReference(_containerName);

// Retrieve reference to a blob.
var blob = container.GetBlockBlobReference(blobName);
await container.CreateIfNotExistsAsync();

// Upload blob.
stream.Position = 0;
// TODO 7: Asyncronously upload the blob from the memory stream.
// COMPLETE: await blob...;

successful = true;
}
catch (Exception e)
{
_log.Error($"Could not upload CSV file: {e.Message}", e);
successful = false;
}
}
}

return successful;
}

/// <summary>
/// Used for mapping from a LicensePlateDataDocument object to a LicensePlateData object.
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
private static LicensePlateData ToLicensePlateData(LicensePlateDataDocument source)
{
return new LicensePlateData
{
FileName = source.fileName,
LicensePlateText = source.licensePlateText,
TimeStamp = source.Timestamp
};
}
}
}
Loading

0 comments on commit 3b92698

Please sign in to comment.