Skip to content

Commit

Permalink
Rename Repo to Repository and minor changes / Import samples project (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
azabbasi authored Feb 24, 2021
1 parent 40896b9 commit f784e78
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Iot.ModelsRepository.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{1FC8A3EA-3C0D-4DDF-B710-A7091F2CEBB1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModelsRepositoryClientSamples", "samples\ModelsRepositoryClientSamples\ModelsRepositoryClientSamples.csproj", "{51E4AB9E-46F3-450C-B52A-C4C6378E8BA3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -27,6 +29,10 @@ Global
{1FC8A3EA-3C0D-4DDF-B710-A7091F2CEBB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FC8A3EA-3C0D-4DDF-B710-A7091F2CEBB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FC8A3EA-3C0D-4DDF-B710-A7091F2CEBB1}.Release|Any CPU.Build.0 = Release|Any CPU
{51E4AB9E-46F3-450C-B52A-C4C6378E8BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51E4AB9E-46F3-450C-B52A-C4C6378E8BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51E4AB9E-46F3-450C-B52A-C4C6378E8BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51E4AB9E-46F3-450C-B52A-C4C6378E8BA3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1;net5.0</TargetFramework>
<RootNamespace>Azure.Iot.ModelsRepository.Samples</RootNamespace>
</PropertyGroup>

<ItemGroup>
<AdditionalFiles Include="..\readme.md" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Azure.Iot.ModelsRepository.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Net;
using System.Threading.Tasks;

namespace Azure.Iot.ModelsRepository.Samples
{
public class Program
{
public static async Task Main(string[] args)
{
// Forward all the events written to the console output with a specific format.
using AzureEventSourceListener listener = new AzureEventSourceListener(
(e, message) => Console.WriteLine("[{0:HH:mm:ss:fff}][{1}] {2}", DateTimeOffset.Now, e.Level, message),
level: EventLevel.Verbose);

await ResolveExistingAsync();
await TryResolveButNotFoundAsync();
}

private static async Task ResolveExistingAsync()
{
var dtmi = "dtmi:com:example:TemperatureController;1";
var client = new ModelsRepositoryClient();

IDictionary<string, string> models = await client.ResolveAsync(dtmi).ConfigureAwait(false);

Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces.");
}

private static async Task TryResolveButNotFoundAsync()
{
var dtmi = "dtmi:com:example:NotFound;1";
var client = new ModelsRepositoryClient();

try
{
IDictionary<string, string> models = await client.ResolveAsync(dtmi).ConfigureAwait(false);
Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces.");
}
catch (RequestFailedException ex) when (ex.Status == (int)HttpStatusCode.NotFound)
{
Console.WriteLine($"{dtmi} was not found in the default public models repository: {ex.Message}");
}
}
}
}
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class LocalModelFetcher : IModelFetcher
private readonly bool _tryExpanded;
private readonly ClientDiagnostics _clientDiagnostics;

public LocalModelFetcher(ClientDiagnostics clientDiagnostics, ModelsRepoClientOptions clientOptions)
public LocalModelFetcher(ClientDiagnostics clientDiagnostics, ModelsRepositoryClientOptions clientOptions)
{
_clientDiagnostics = clientDiagnostics;
_tryExpanded = clientOptions.DependencyResolution == DependencyResolutionOption.TryFromExpanded;
Expand Down Expand Up @@ -54,7 +54,7 @@ public FetchResult Fetch(string dtmi, Uri repositoryUri, CancellationToken cance
cancellationToken.ThrowIfCancellationRequested();

string tryContentPath = work.Dequeue();
ModelsRepoEventSource.Instance.FetchingModelContent(tryContentPath);
ModelsRepositoryEventSource.Instance.FetchingModelContent(tryContentPath);

if (File.Exists(tryContentPath))
{
Expand All @@ -65,7 +65,7 @@ public FetchResult Fetch(string dtmi, Uri repositoryUri, CancellationToken cance
};
}

ModelsRepoEventSource.Instance.ErrorFetchingModelContent(tryContentPath);
ModelsRepositoryEventSource.Instance.ErrorFetchingModelContent(tryContentPath);
fnfError = string.Format(CultureInfo.CurrentCulture, ServiceStrings.ErrorFetchingModelContent, tryContentPath);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -23,7 +24,7 @@ internal class RemoteModelFetcher : IModelFetcher
private readonly ClientDiagnostics _clientDiagnostics;
private readonly bool _tryExpanded;

public RemoteModelFetcher(ClientDiagnostics clientDiagnostics, ModelsRepoClientOptions clientOptions)
public RemoteModelFetcher(ClientDiagnostics clientDiagnostics, ModelsRepositoryClientOptions clientOptions)
{
_pipeline = CreatePipeline(clientOptions);
_tryExpanded = clientOptions.DependencyResolution == DependencyResolutionOption.TryFromExpanded;
Expand All @@ -45,7 +46,7 @@ public FetchResult Fetch(string dtmi, Uri repositoryUri, CancellationToken cance
cancellationToken.ThrowIfCancellationRequested();

string tryContentPath = work.Dequeue();
ModelsRepoEventSource.Instance.FetchingModelContent(tryContentPath);
ModelsRepositoryEventSource.Instance.FetchingModelContent(tryContentPath);

try
{
Expand Down Expand Up @@ -82,13 +83,15 @@ public async Task<FetchResult> FetchAsync(string dtmi, Uri repositoryUri, Cancel
Queue<string> work = PrepareWork(dtmi, repositoryUri);

string remoteFetchError = string.Empty;
RequestFailedException requestFailedExceptionThrown = null;
Exception genericExceptionThrown = null;

while (work.Count != 0)
{
cancellationToken.ThrowIfCancellationRequested();

string tryContentPath = work.Dequeue();
ModelsRepoEventSource.Instance.FetchingModelContent(tryContentPath);
ModelsRepositoryEventSource.Instance.FetchingModelContent(tryContentPath);

try
{
Expand All @@ -99,15 +102,39 @@ public async Task<FetchResult> FetchAsync(string dtmi, Uri repositoryUri, Cancel
Path = tryContentPath
};
}
catch (Exception)
catch (RequestFailedException ex)
{
requestFailedExceptionThrown = ex;
}
catch (Exception ex)
{
genericExceptionThrown = ex;
}

if (genericExceptionThrown != null || requestFailedExceptionThrown != null)
{
remoteFetchError =
$"{string.Format(CultureInfo.CurrentCulture, ServiceStrings.GenericResolverError, dtmi)} " +
string.Format(CultureInfo.CurrentCulture, StandardStrings.ErrorFetchingModelContent, tryContentPath);
}
}

throw new RequestFailedException(remoteFetchError);
if (requestFailedExceptionThrown != null)
{
throw new RequestFailedException(
requestFailedExceptionThrown.Status,
remoteFetchError,
requestFailedExceptionThrown.ErrorCode,
requestFailedExceptionThrown);
}
else
{
throw new RequestFailedException(
(int)HttpStatusCode.BadRequest,
remoteFetchError,
null,
genericExceptionThrown);
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -219,7 +246,7 @@ private static async Task<string> GetContentAsync(Stream content, CancellationTo
return root.GetRawText();
}

private static HttpPipeline CreatePipeline(ModelsRepoClientOptions options)
private static HttpPipeline CreatePipeline(ModelsRepositoryClientOptions options)
{
return HttpPipelineBuilder.Build(options);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,84 +6,56 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Pipeline;

namespace Azure.Iot.ModelsRepository
{
/// <summary>
/// The ModelsRepoClient class supports operations against DTDL model repositories following the
/// The ModelsRepositoryClient class supports operations against DTDL model repositories following the
/// conventions of the Azure IoT Plug and Play Models repository.
/// </summary>
public class ModelsRepoClient
public class ModelsRepositoryClient
{
private readonly RepositoryHandler _repositoryHandler;
private readonly ClientDiagnostics _clientDiagnostics;
private readonly ModelsRepositoryClientOptions _clientOptions;

/// <summary>
/// Initializes the ModelsRepoClient with default client options while pointing to
/// Initializes the ModelsRepositoryClient with default client options while pointing to
/// the Azure IoT Plug and Play Models repository https://devicemodels.azure.com for resolution.
/// </summary>
public ModelsRepoClient() : this(new Uri(DefaultModelsRepository), new ModelsRepoClientOptions()) { }
public ModelsRepositoryClient() : this(DefaultModelsRepository, new ModelsRepositoryClientOptions()) { }

/// <summary>
/// Initializes the ModelsRepoClient with default client options while pointing to
/// a custom <paramref name="repositoryUri"/> for resolution.
/// </summary>
/// <param name="repositoryUri">
/// The model repository Uri value. This can be a remote endpoint or local directory.
/// </param>
public ModelsRepoClient(Uri repositoryUri) : this(repositoryUri, new ModelsRepoClientOptions()) { }

/// <summary>
/// Initializes the ModelsRepoClient with custom client <paramref name="options"/> while pointing to
/// Initializes the ModelsRepositoryClient with custom client <paramref name="options"/> while pointing to
/// the Azure IoT Plug and Play Model repository https://devicemodels.azure.com for resolution.
/// </summary>
/// <param name="options">
/// ModelsRepoClientOptions to configure resolution and client behavior.
/// ModelsRepositoryClientOptions to configure resolution and client behavior.
/// </param>
public ModelsRepoClient(ModelsRepoClientOptions options) : this(new Uri(DefaultModelsRepository), options) { }
public ModelsRepositoryClient(ModelsRepositoryClientOptions options) : this(DefaultModelsRepository, options) { }

/// <summary>
/// Initializes the ModelsRepoClient with default client options while pointing to
/// a custom <paramref name="repositoryUriStr"/> for resolution.
/// </summary>
/// <param name="repositoryUriStr">
/// The model repository Uri in string format. This can be a remote endpoint or local directory.
/// </param>
public ModelsRepoClient(string repositoryUriStr) : this(repositoryUriStr, new ModelsRepoClientOptions()) { }

/// <summary>
/// Initializes the ModelsRepoClient with custom client <paramref name="options"/> while pointing to
/// a custom <paramref name="repositoryUriStr"/> for resolution.
/// </summary>
/// <param name="repositoryUriStr">
/// The model repository Uri in string format. This can be a remote endpoint or local directory.
/// </param>
/// <param name="options">
/// ModelsRepoClientOptions to configure resolution and client behavior.
/// </param>
public ModelsRepoClient(string repositoryUriStr, ModelsRepoClientOptions options)
: this(new Uri(repositoryUriStr), options) { }

/// <summary>
/// Initializes the ModelsRepoClient with custom client <paramref name="options"/> while pointing to
/// Initializes the ModelsRepositoryClient with custom client <paramref name="options"/> while pointing to
/// a custom <paramref name="repositoryUri"/> for resolution.
/// </summary>
/// <param name="repositoryUri">
/// The model repository Uri. This can be a remote endpoint or local directory.
/// </param>
/// <param name="options">
/// ModelsRepoClientOptions to configure resolution and client behavior.
/// ModelsRepositoryClientOptions to configure resolution and client behavior.
/// </param>
public ModelsRepoClient(Uri repositoryUri, ModelsRepoClientOptions options)
public ModelsRepositoryClient(Uri repositoryUri, ModelsRepositoryClientOptions options = default)
{
Argument.AssertNotNull(options, nameof(options));
if (options == null)
{
options = new ModelsRepositoryClientOptions();
}

ClientOptions = options;
RepositoryUri = repositoryUri;
_clientOptions = options;
_clientDiagnostics = new ClientDiagnostics(options);
_repositoryHandler = new RepositoryHandler(RepositoryUri, _clientDiagnostics, ClientOptions);
_repositoryHandler = new RepositoryHandler(RepositoryUri, _clientDiagnostics, _clientOptions);
}

/// <summary>
Expand All @@ -102,7 +74,7 @@ public ModelsRepoClient(Uri repositoryUri, ModelsRepoClientOptions options)
Justification = "<Pending>")]
public virtual async Task<IDictionary<string, string>> ResolveAsync(string dtmi, CancellationToken cancellationToken = default)
{
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepoClient)}.{nameof(Resolve)}");
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepositoryClient)}.{nameof(Resolve)}");
scope.Start();
try
{
Expand Down Expand Up @@ -131,7 +103,7 @@ public virtual async Task<IDictionary<string, string>> ResolveAsync(string dtmi,
Justification = "<Pending>")]
public virtual IDictionary<string, string> Resolve(string dtmi, CancellationToken cancellationToken = default)
{
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepoClient)}.{nameof(Resolve)}");
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepositoryClient)}.{nameof(Resolve)}");
scope.Start();

try
Expand All @@ -158,7 +130,7 @@ public virtual IDictionary<string, string> Resolve(string dtmi, CancellationToke
[SuppressMessage("Usage", "AZC0015:Unexpected client method return type.", Justification = "<Pending>")]
public virtual async Task<IDictionary<string, string>> ResolveAsync(IEnumerable<string> dtmis, CancellationToken cancellationToken = default)
{
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepoClient)}.{nameof(Resolve)}");
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepositoryClient)}.{nameof(Resolve)}");
scope.Start();

try
Expand All @@ -185,7 +157,7 @@ public virtual async Task<IDictionary<string, string>> ResolveAsync(IEnumerable<
[SuppressMessage("Usage", "AZC0015:Unexpected client method return type.", Justification = "<Pending>")]
public virtual IDictionary<string, string> Resolve(IEnumerable<string> dtmis, CancellationToken cancellationToken = default)
{
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepoClient)}.{nameof(Resolve)}");
using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ModelsRepositoryClient)}.{nameof(Resolve)}");
scope.Start();

try
Expand All @@ -205,18 +177,13 @@ public virtual IDictionary<string, string> Resolve(IEnumerable<string> dtmis, Ca
public static bool IsValidDtmi(string dtmi) => DtmiConventions.IsDtmi(dtmi);

/// <summary>
/// Gets the Uri associated with the ModelsRepoClient instance.
/// Gets the Uri associated with the ModelsRepositoryClient instance.
/// </summary>
public Uri RepositoryUri { get; }

/// <summary>
/// Gets the ModelsRepoClientOptions associated with the ModelsRepoClient instance.
/// </summary>
public ModelsRepoClientOptions ClientOptions { get; }

/// <summary>
/// The global Azure IoT Models Repository endpoint used by default.
/// </summary>
public static string DefaultModelsRepository => ModelRepositoryConstants.DefaultModelsRepository;
public static Uri DefaultModelsRepository => new Uri(ModelRepositoryConstants.DefaultModelsRepository);
}
}
Loading

0 comments on commit f784e78

Please sign in to comment.