diff --git a/src/SQL2Linked/Implementations/ResourceStructuralData.cs b/src/SQL2Linked/Implementations/ResourceStructuralData.cs index 2202e877bf4ed8214d927d1dc32be73c07052b2c..cccc6af8a0e031b08006d01c79a7e212a13b32f9 100644 --- a/src/SQL2Linked/Implementations/ResourceStructuralData.cs +++ b/src/SQL2Linked/Implementations/ResourceStructuralData.cs @@ -147,7 +147,7 @@ namespace SQL2Linked.Implementations "}" }; - var resultSet = QueryEndpoint.QueryWithResultSet(cmdString.ToString()); + var resultSet = WrapRequest(() => RdfStoreConnector.QueryEndpoint.QueryWithResultSet(cmdString.ToString())); foreach (var result in resultSet) { @@ -211,7 +211,7 @@ namespace SQL2Linked.Implementations "WHERE { @applicationProfile <http://www.w3.org/ns/shacl#targetClass> ?targetClass }" }; targetClassCmdString.SetUri("applicationProfile", new Uri(entry.ApplicationProfile)); - var targetClassResultSet = QueryEndpoint.QueryWithResultSet(targetClassCmdString.ToString()); + var targetClassResultSet = WrapRequest(() => RdfStoreConnector.QueryEndpoint.QueryWithResultSet(targetClassCmdString.ToString())); var targetClass = entry.ApplicationProfile; foreach (var result in targetClassResultSet) diff --git a/src/SQL2Linked/SQL2Linked.csproj b/src/SQL2Linked/SQL2Linked.csproj index eea70a16a6b4b61afce43d1dddf6c9ebb1712908..6611386e72de8af2f1a4d6cf73b7b3149556496e 100644 --- a/src/SQL2Linked/SQL2Linked.csproj +++ b/src/SQL2Linked/SQL2Linked.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> @@ -10,6 +10,7 @@ <ItemGroup> <PackageReference Include="Coscine.Database" Version="2.*-*" /> <PackageReference Include="Coscine.Metadata" Version="2.*-*" /> + <PackageReference Include="Polly" Version="7.2.3" /> </ItemGroup> </Project> diff --git a/src/SQL2Linked/StructuralData.cs b/src/SQL2Linked/StructuralData.cs index 0b86a3aa6bf1e17e5c4003c939c186e9cf384c2a..53c7a0c18a5bb0199bbd69a79f2585ac048734dc 100644 --- a/src/SQL2Linked/StructuralData.cs +++ b/src/SQL2Linked/StructuralData.cs @@ -1,8 +1,8 @@ -using Coscine.Configuration; +using Polly; +using Coscine.Configuration; using Coscine.Database.Models; using Coscine.Metadata; using VDS.RDF; -using VDS.RDF.Query; namespace SQL2Linked { @@ -12,7 +12,6 @@ namespace SQL2Linked public ConsulConfiguration Configuration { get; init; } public RdfStoreConnector RdfStoreConnector { get; init; } public static string Prefix { get; set; } - public readonly SparqlRemoteEndpoint QueryEndpoint; public StructuralData() { @@ -20,7 +19,11 @@ namespace SQL2Linked RdfStoreConnector = new RdfStoreConnector(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")); Model = new T(); Prefix = Configuration.GetStringAndWait("coscine/global/epic/prefix"); - QueryEndpoint = new SparqlRemoteEndpoint(new Uri(Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url"))); + // 100 second timeout + var timeout = 100000; + RdfStoreConnector.QueryEndpoint.Timeout = timeout; + RdfStoreConnector.UpdateEndpoint.Timeout = timeout; + RdfStoreConnector.ReadWriteSparqlConnector.Timeout = timeout; } public abstract IEnumerable<IGraph> ConvertToLinkedData(IEnumerable<S> entries); @@ -46,17 +49,17 @@ namespace SQL2Linked foreach (var graph in graphs) { Console.WriteLine($" ({graph.BaseUri})"); - var exists = RdfStoreConnector.HasGraph(graph.BaseUri); + var exists = WrapRequest(() => RdfStoreConnector.HasGraph(graph.BaseUri)); if (exists) { Console.WriteLine($" - Graph {graph.BaseUri} exists"); // Clear the existing graph from the store - RdfStoreConnector.ClearGraph(graph.BaseUri); + WrapRequest(() => RdfStoreConnector.ClearGraph(graph.BaseUri)); Console.WriteLine($" - Cleared Graph {graph.BaseUri}"); } // Add the new graph to the store - RdfStoreConnector.AddGraph(graph); + WrapRequest(() => RdfStoreConnector.AddGraph(graph)); Console.WriteLine($" - Graph {graph.BaseUri} added successfully"); Console.WriteLine(); } @@ -103,5 +106,33 @@ namespace SQL2Linked ); } } + + /// <summary> + /// Retry Virtuoso Requests since they sometimes just fail + /// </summary> + /// <typeparam name="W"></typeparam> + /// <param name="function"></param> + /// <returns></returns> + public void WrapRequest(Action action) + { + Policy + .Handle<Exception>() + .WaitAndRetry(5, retryNumber => TimeSpan.FromMilliseconds(200)) + .Execute(() => action.Invoke()); + } + + /// <summary> + /// Retry Virtuoso Requests since they sometimes just fail + /// </summary> + /// <typeparam name="W"></typeparam> + /// <param name="function"></param> + /// <returns></returns> + public W WrapRequest<W>(Func<W> function) + { + return Policy + .Handle<Exception>() + .WaitAndRetry(5, retryNumber => TimeSpan.FromMilliseconds(200)) + .ExecuteAndCapture(() => function.Invoke()).Result; + } } }