mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-04 06:23:09 +00:00
Extracts codexClient assembly
This commit is contained in:
parent
48f4614e5d
commit
4a151880d4
@ -9,6 +9,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FileUtils\FileUtils.csproj" />
|
<ProjectReference Include="..\FileUtils\FileUtils.csproj" />
|
||||||
<ProjectReference Include="..\KubernetesWorkflow\KubernetesWorkflow.csproj" />
|
<ProjectReference Include="..\KubernetesWorkflow\KubernetesWorkflow.csproj" />
|
||||||
|
<ProjectReference Include="..\WebUtils\WebUtils.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
using WebUtils;
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
@ -8,16 +9,16 @@ namespace Core
|
|||||||
private readonly IToolsFactory toolsFactory;
|
private readonly IToolsFactory toolsFactory;
|
||||||
private readonly PluginManager manager = new PluginManager();
|
private readonly PluginManager manager = new PluginManager();
|
||||||
|
|
||||||
public EntryPoint(ILog log, Configuration configuration, string fileManagerRootFolder, ITimeSet timeSet)
|
public EntryPoint(ILog log, Configuration configuration, string fileManagerRootFolder, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8STimeSet)
|
||||||
{
|
{
|
||||||
toolsFactory = new ToolsFactory(log, configuration, fileManagerRootFolder, timeSet);
|
toolsFactory = new ToolsFactory(log, configuration, fileManagerRootFolder, webCallTimeSet, k8STimeSet);
|
||||||
|
|
||||||
Tools = toolsFactory.CreateTools();
|
Tools = toolsFactory.CreateTools();
|
||||||
manager.InstantiatePlugins(PluginFinder.GetPluginTypes(), toolsFactory);
|
manager.InstantiatePlugins(PluginFinder.GetPluginTypes(), toolsFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntryPoint(ILog log, Configuration configuration, string fileManagerRootFolder)
|
public EntryPoint(ILog log, Configuration configuration, string fileManagerRootFolder)
|
||||||
: this(log, configuration, fileManagerRootFolder, new DefaultTimeSet())
|
: this(log, configuration, fileManagerRootFolder, new DefaultWebCallTimeSet(), new DefaultK8sTimeSet())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
using FileUtils;
|
using FileUtils;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
using WebUtils;
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
public interface IPluginTools : IWorkflowTool, ILogTool, IHttpFactoryTool, IFileTool
|
public interface IPluginTools : IWorkflowTool, ILogTool, IHttpFactory, IFileTool
|
||||||
{
|
{
|
||||||
ITimeSet TimeSet { get; }
|
IWebCallTimeSet WebCallTimeSet { get; }
|
||||||
|
IK8sTimeSet K8STimeSet { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes kubernetes and tracked file resources.
|
/// Deletes kubernetes and tracked file resources.
|
||||||
@ -25,13 +27,6 @@ namespace Core
|
|||||||
ILog GetLog();
|
ILog GetLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IHttpFactoryTool
|
|
||||||
{
|
|
||||||
IHttp CreateHttp(string id, Action<HttpClient> onClientCreated);
|
|
||||||
IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, ITimeSet timeSet);
|
|
||||||
IHttp CreateHttp(string id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFileTool
|
public interface IFileTool
|
||||||
{
|
{
|
||||||
IFileManager GetFileManager();
|
IFileManager GetFileManager();
|
||||||
@ -40,18 +35,22 @@ namespace Core
|
|||||||
internal class PluginTools : IPluginTools
|
internal class PluginTools : IPluginTools
|
||||||
{
|
{
|
||||||
private readonly WorkflowCreator workflowCreator;
|
private readonly WorkflowCreator workflowCreator;
|
||||||
|
private readonly HttpFactory httpFactory;
|
||||||
private readonly IFileManager fileManager;
|
private readonly IFileManager fileManager;
|
||||||
private readonly LogPrefixer log;
|
private readonly LogPrefixer log;
|
||||||
|
|
||||||
internal PluginTools(ILog log, WorkflowCreator workflowCreator, string fileManagerRootFolder, ITimeSet timeSet)
|
internal PluginTools(ILog log, WorkflowCreator workflowCreator, string fileManagerRootFolder, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8STimeSet)
|
||||||
{
|
{
|
||||||
this.log = new LogPrefixer(log);
|
this.log = new LogPrefixer(log);
|
||||||
this.workflowCreator = workflowCreator;
|
this.workflowCreator = workflowCreator;
|
||||||
TimeSet = timeSet;
|
httpFactory = new HttpFactory(log, webCallTimeSet);
|
||||||
|
WebCallTimeSet = webCallTimeSet;
|
||||||
|
K8STimeSet = k8STimeSet;
|
||||||
fileManager = new FileManager(log, fileManagerRootFolder);
|
fileManager = new FileManager(log, fileManagerRootFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITimeSet TimeSet { get; }
|
public IWebCallTimeSet WebCallTimeSet { get; }
|
||||||
|
public IK8sTimeSet K8STimeSet { get; }
|
||||||
|
|
||||||
public void ApplyLogPrefix(string prefix)
|
public void ApplyLogPrefix(string prefix)
|
||||||
{
|
{
|
||||||
@ -60,17 +59,17 @@ namespace Core
|
|||||||
|
|
||||||
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated)
|
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated)
|
||||||
{
|
{
|
||||||
return CreateHttp(id, onClientCreated, TimeSet);
|
return httpFactory.CreateHttp(id, onClientCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, ITimeSet ts)
|
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, IWebCallTimeSet timeSet)
|
||||||
{
|
{
|
||||||
return new Http(id, log, ts, onClientCreated);
|
return httpFactory.CreateHttp(id, onClientCreated, timeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttp CreateHttp(string id)
|
public IHttp CreateHttp(string id)
|
||||||
{
|
{
|
||||||
return new Http(id, log, TimeSet);
|
return httpFactory.CreateHttp(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IStartupWorkflow CreateWorkflow(string? namespaceOverride = null)
|
public IStartupWorkflow CreateWorkflow(string? namespaceOverride = null)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
using WebUtils;
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
@ -13,19 +14,21 @@ namespace Core
|
|||||||
private readonly ILog log;
|
private readonly ILog log;
|
||||||
private readonly WorkflowCreator workflowCreator;
|
private readonly WorkflowCreator workflowCreator;
|
||||||
private readonly string fileManagerRootFolder;
|
private readonly string fileManagerRootFolder;
|
||||||
private readonly ITimeSet timeSet;
|
private readonly IWebCallTimeSet webCallTimeSet;
|
||||||
|
private readonly IK8sTimeSet k8STimeSet;
|
||||||
|
|
||||||
public ToolsFactory(ILog log, Configuration configuration, string fileManagerRootFolder, ITimeSet timeSet)
|
public ToolsFactory(ILog log, Configuration configuration, string fileManagerRootFolder, IWebCallTimeSet webCallTimeSet, IK8sTimeSet k8STimeSet)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
workflowCreator = new WorkflowCreator(log, configuration);
|
workflowCreator = new WorkflowCreator(log, configuration);
|
||||||
this.fileManagerRootFolder = fileManagerRootFolder;
|
this.fileManagerRootFolder = fileManagerRootFolder;
|
||||||
this.timeSet = timeSet;
|
this.webCallTimeSet = webCallTimeSet;
|
||||||
|
this.k8STimeSet = k8STimeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginTools CreateTools()
|
public PluginTools CreateTools()
|
||||||
{
|
{
|
||||||
return new PluginTools(log, workflowCreator, fileManagerRootFolder, timeSet);
|
return new PluginTools(log, workflowCreator, fileManagerRootFolder, webCallTimeSet, k8STimeSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
Framework/KubernetesWorkflow/K8sTimeSet.cs
Normal file
42
Framework/KubernetesWorkflow/K8sTimeSet.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
public interface IK8sTimeSet
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// After a failed K8s operation, wait this long before trying again.
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan K8sOperationRetryDelay();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum total time to attempt to perform a successful k8s operation.
|
||||||
|
/// If k8s operations fail during this timespan, retries will be made.
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan K8sOperationTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DefaultK8sTimeSet : IK8sTimeSet
|
||||||
|
{
|
||||||
|
public TimeSpan K8sOperationRetryDelay()
|
||||||
|
{
|
||||||
|
return TimeSpan.FromSeconds(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan K8sOperationTimeout()
|
||||||
|
{
|
||||||
|
return TimeSpan.FromMinutes(30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LongK8sTimeSet : IK8sTimeSet
|
||||||
|
{
|
||||||
|
public TimeSpan K8sOperationRetryDelay()
|
||||||
|
{
|
||||||
|
return TimeSpan.FromSeconds(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan K8sOperationTimeout()
|
||||||
|
{
|
||||||
|
return TimeSpan.FromHours(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Framework/Utils/EthAccount.cs
Normal file
20
Framework/Utils/EthAccount.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class EthAccount
|
||||||
|
{
|
||||||
|
public EthAccount(EthAddress ethAddress, string privateKey)
|
||||||
|
{
|
||||||
|
EthAddress = ethAddress;
|
||||||
|
PrivateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EthAddress EthAddress { get; }
|
||||||
|
public string PrivateKey { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return EthAddress.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GethPlugin
|
namespace Utils
|
||||||
{
|
{
|
||||||
public interface IHasEthAddress
|
public interface IHasEthAddress
|
||||||
{
|
{
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GethPlugin
|
namespace Utils
|
||||||
{
|
{
|
||||||
public class Ether : IComparable<Ether>
|
public class Ether : IComparable<Ether>
|
||||||
{
|
{
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace CodexContractsPlugin
|
namespace Utils
|
||||||
{
|
{
|
||||||
public class TestToken : IComparable<TestToken>
|
public class TestToken : IComparable<TestToken>
|
||||||
{
|
{
|
||||||
@ -1,11 +1,10 @@
|
|||||||
using Logging;
|
using System.Net.Http.Headers;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Serialization = Newtonsoft.Json.Serialization;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace Core
|
namespace WebUtils
|
||||||
{
|
{
|
||||||
public interface IEndpoint
|
public interface IEndpoint
|
||||||
{
|
{
|
||||||
@ -119,7 +118,7 @@ namespace Core
|
|||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
var deserialized = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
|
var deserialized = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
|
||||||
{
|
{
|
||||||
Error = delegate (object? sender, Serialization.ErrorEventArgs args)
|
Error = delegate (object? sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.CurrentObject == args.ErrorContext.OriginalObject)
|
if (args.CurrentObject == args.ErrorContext.OriginalObject)
|
||||||
{
|
{
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace Core
|
namespace WebUtils
|
||||||
{
|
{
|
||||||
public interface IHttp
|
public interface IHttp
|
||||||
{
|
{
|
||||||
@ -16,16 +16,16 @@ namespace Core
|
|||||||
private static object lockLock = new object();
|
private static object lockLock = new object();
|
||||||
private static readonly Dictionary<string, object> httpLocks = new Dictionary<string, object>();
|
private static readonly Dictionary<string, object> httpLocks = new Dictionary<string, object>();
|
||||||
private readonly ILog log;
|
private readonly ILog log;
|
||||||
private readonly ITimeSet timeSet;
|
private readonly IWebCallTimeSet timeSet;
|
||||||
private readonly Action<HttpClient> onClientCreated;
|
private readonly Action<HttpClient> onClientCreated;
|
||||||
private readonly string id;
|
private readonly string id;
|
||||||
|
|
||||||
internal Http(string id, ILog log, ITimeSet timeSet)
|
internal Http(string id, ILog log, IWebCallTimeSet timeSet)
|
||||||
: this(id, log, timeSet, DoNothing)
|
: this(id, log, timeSet, DoNothing)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Http(string id, ILog log, ITimeSet timeSet, Action<HttpClient> onClientCreated)
|
internal Http(string id, ILog log, IWebCallTimeSet timeSet, Action<HttpClient> onClientCreated)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
43
Framework/WebUtils/HttpFactory.cs
Normal file
43
Framework/WebUtils/HttpFactory.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using Logging;
|
||||||
|
|
||||||
|
namespace WebUtils
|
||||||
|
{
|
||||||
|
public interface IHttpFactory
|
||||||
|
{
|
||||||
|
IHttp CreateHttp(string id, Action<HttpClient> onClientCreated);
|
||||||
|
IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, IWebCallTimeSet timeSet);
|
||||||
|
IHttp CreateHttp(string id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HttpFactory : IHttpFactory
|
||||||
|
{
|
||||||
|
private readonly ILog log;
|
||||||
|
private readonly IWebCallTimeSet defaultTimeSet;
|
||||||
|
|
||||||
|
public HttpFactory(ILog log)
|
||||||
|
: this (log, new DefaultWebCallTimeSet())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpFactory(ILog log, IWebCallTimeSet defaultTimeSet)
|
||||||
|
{
|
||||||
|
this.log = log;
|
||||||
|
this.defaultTimeSet = defaultTimeSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated)
|
||||||
|
{
|
||||||
|
return CreateHttp(id, onClientCreated, defaultTimeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHttp CreateHttp(string id, Action<HttpClient> onClientCreated, IWebCallTimeSet ts)
|
||||||
|
{
|
||||||
|
return new Http(id, log, ts, onClientCreated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHttp CreateHttp(string id)
|
||||||
|
{
|
||||||
|
return new Http(id, log, defaultTimeSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
namespace Core
|
namespace WebUtils
|
||||||
{
|
{
|
||||||
public interface ITimeSet
|
public interface IWebCallTimeSet
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout for a single HTTP call.
|
/// Timeout for a single HTTP call.
|
||||||
@ -17,20 +17,9 @@
|
|||||||
/// After a failed HTTP call, wait this long before trying again.
|
/// After a failed HTTP call, wait this long before trying again.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TimeSpan HttpCallRetryDelay();
|
TimeSpan HttpCallRetryDelay();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// After a failed K8s operation, wait this long before trying again.
|
|
||||||
/// </summary>
|
|
||||||
TimeSpan K8sOperationRetryDelay();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum total time to attempt to perform a successful k8s operation.
|
|
||||||
/// If k8s operations fail during this timespan, retries will be made.
|
|
||||||
/// </summary>
|
|
||||||
TimeSpan K8sOperationTimeout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DefaultTimeSet : ITimeSet
|
public class DefaultWebCallTimeSet : IWebCallTimeSet
|
||||||
{
|
{
|
||||||
public TimeSpan HttpCallTimeout()
|
public TimeSpan HttpCallTimeout()
|
||||||
{
|
{
|
||||||
@ -46,19 +35,9 @@
|
|||||||
{
|
{
|
||||||
return TimeSpan.FromSeconds(1);
|
return TimeSpan.FromSeconds(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan K8sOperationRetryDelay()
|
|
||||||
{
|
|
||||||
return TimeSpan.FromSeconds(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSpan K8sOperationTimeout()
|
|
||||||
{
|
|
||||||
return TimeSpan.FromMinutes(30);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LongTimeSet : ITimeSet
|
public class LongWebCallTimeSet : IWebCallTimeSet
|
||||||
{
|
{
|
||||||
public TimeSpan HttpCallTimeout()
|
public TimeSpan HttpCallTimeout()
|
||||||
{
|
{
|
||||||
@ -74,15 +53,5 @@
|
|||||||
{
|
{
|
||||||
return TimeSpan.FromSeconds(20);
|
return TimeSpan.FromSeconds(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan K8sOperationRetryDelay()
|
|
||||||
{
|
|
||||||
return TimeSpan.FromSeconds(30);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSpan K8sOperationTimeout()
|
|
||||||
{
|
|
||||||
return TimeSpan.FromHours(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
Framework/WebUtils/WebUtils.csproj
Normal file
18
Framework/WebUtils/WebUtils.csproj
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Logging\Logging.csproj" />
|
||||||
|
<ProjectReference Include="..\Utils\Utils.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -1,26 +1,25 @@
|
|||||||
using CodexOpenApi;
|
using CodexOpenApi;
|
||||||
using Core;
|
|
||||||
using GethPlugin;
|
|
||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
using WebUtils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public class CodexAccess
|
public class CodexAccess
|
||||||
{
|
{
|
||||||
private readonly ILog log;
|
private readonly ILog log;
|
||||||
private readonly IPluginTools tools;
|
private readonly IHttpFactory httpFactory;
|
||||||
private readonly IProcessControl processControl;
|
private readonly IProcessControl processControl;
|
||||||
private ICodexInstance instance;
|
private ICodexInstance instance;
|
||||||
private readonly Mapper mapper = new Mapper();
|
private readonly Mapper mapper = new Mapper();
|
||||||
|
|
||||||
public CodexAccess(IPluginTools tools, IProcessControl processControl, ICodexInstance instance, ICrashWatcher crashWatcher)
|
public CodexAccess(ILog log, IHttpFactory httpFactory, IProcessControl processControl, ICodexInstance instance, ICrashWatcher crashWatcher)
|
||||||
{
|
{
|
||||||
this.tools = tools;
|
this.log = log;
|
||||||
|
this.httpFactory = httpFactory;
|
||||||
this.processControl = processControl;
|
this.processControl = processControl;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
log = tools.GetLog();
|
|
||||||
CrashWatcher = crashWatcher;
|
CrashWatcher = crashWatcher;
|
||||||
|
|
||||||
CrashWatcher.Start();
|
CrashWatcher.Start();
|
||||||
@ -103,19 +102,14 @@ namespace CodexPlugin
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public string UploadFile(UploadInput uploadInput, Action<Failure> onFailure)
|
public string UploadFile(UploadInput uploadInput)
|
||||||
{
|
{
|
||||||
return OnCodex(
|
return OnCodex(api => api.UploadAsync(uploadInput.ContentType, uploadInput.ContentDisposition, uploadInput.FileStream));
|
||||||
api => api.UploadAsync(uploadInput.ContentType, uploadInput.ContentDisposition, uploadInput.FileStream),
|
|
||||||
CreateRetryConfig(nameof(UploadFile), onFailure));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream DownloadFile(string contentId, Action<Failure> onFailure)
|
public Stream DownloadFile(string contentId)
|
||||||
{
|
{
|
||||||
var fileResponse = OnCodex(
|
var fileResponse = OnCodex(api => api.DownloadNetworkStreamAsync(contentId));
|
||||||
api => api.DownloadNetworkStreamAsync(contentId),
|
|
||||||
CreateRetryConfig(nameof(DownloadFile), onFailure));
|
|
||||||
|
|
||||||
if (fileResponse.StatusCode != 200) throw new Exception("Download failed with StatusCode: " + fileResponse.StatusCode);
|
if (fileResponse.StatusCode != 200) throw new Exception("Download failed with StatusCode: " + fileResponse.StatusCode);
|
||||||
return fileResponse.Stream;
|
return fileResponse.Stream;
|
||||||
}
|
}
|
||||||
@ -147,7 +141,6 @@ namespace CodexPlugin
|
|||||||
return JsonConvert.DeserializeObject<LocalDatasetListJson>(str)!;
|
return JsonConvert.DeserializeObject<LocalDatasetListJson>(str)!;
|
||||||
}, nameof(LocalFiles));
|
}, nameof(LocalFiles));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StorageAvailability SalesAvailability(StorageAvailability request)
|
public StorageAvailability SalesAvailability(StorageAvailability request)
|
||||||
@ -227,22 +220,22 @@ namespace CodexPlugin
|
|||||||
processControl.DeleteDataDirFolder(instance);
|
processControl.DeleteDataDirFolder(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T OnCodex<T>(Func<CodexApi, Task<T>> action)
|
private T OnCodex<T>(Func<openapiClient, Task<T>> action)
|
||||||
{
|
{
|
||||||
var result = tools.CreateHttp(GetHttpId(), CheckContainerCrashed).OnClient(client => CallCodex(client, action));
|
var result = httpFactory.CreateHttp(GetHttpId(), CheckContainerCrashed).OnClient(client => CallCodex(client, action));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private T OnCodex<T>(Func<CodexApi, Task<T>> action, Retry retry)
|
private T OnCodex<T>(Func<openapiClient, Task<T>> action, Retry retry)
|
||||||
{
|
{
|
||||||
var result = tools.CreateHttp(GetHttpId(), CheckContainerCrashed).OnClient(client => CallCodex(client, action), retry);
|
var result = httpFactory.CreateHttp(GetHttpId(), CheckContainerCrashed).OnClient(client => CallCodex(client, action), retry);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private T CallCodex<T>(HttpClient client, Func<CodexApi, Task<T>> action)
|
private T CallCodex<T>(HttpClient client, Func<openapiClient, Task<T>> action)
|
||||||
{
|
{
|
||||||
var address = GetAddress();
|
var address = GetAddress();
|
||||||
var api = new CodexApi(client);
|
var api = new openapiClient(client);
|
||||||
api.BaseUrl = $"{address.Host}:{address.Port}/api/codex/v1";
|
api.BaseUrl = $"{address.Host}:{address.Port}/api/codex/v1";
|
||||||
return CrashCheck(() => Time.Wait(action(api)));
|
return CrashCheck(() => Time.Wait(action(api)));
|
||||||
}
|
}
|
||||||
@ -261,7 +254,7 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
private IEndpoint GetEndpoint()
|
private IEndpoint GetEndpoint()
|
||||||
{
|
{
|
||||||
return tools
|
return httpFactory
|
||||||
.CreateHttp(GetHttpId(), CheckContainerCrashed)
|
.CreateHttp(GetHttpId(), CheckContainerCrashed)
|
||||||
.CreateEndpoint(GetAddress(), "/api/codex/v1/", GetName());
|
.CreateEndpoint(GetAddress(), "/api/codex/v1/", GetName());
|
||||||
}
|
}
|
||||||
@ -281,49 +274,6 @@ namespace CodexPlugin
|
|||||||
if (CrashWatcher.HasCrashed()) throw new Exception($"Container {GetName()} has crashed.");
|
if (CrashWatcher.HasCrashed()) throw new Exception($"Container {GetName()} has crashed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Retry CreateRetryConfig(string description, Action<Failure> onFailure)
|
|
||||||
{
|
|
||||||
var timeSet = tools.TimeSet;
|
|
||||||
|
|
||||||
return new Retry(description, timeSet.HttpRetryTimeout(), timeSet.HttpCallRetryDelay(), failure =>
|
|
||||||
{
|
|
||||||
onFailure(failure);
|
|
||||||
Investigate(failure, timeSet);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Investigate(Failure failure, ITimeSet timeSet)
|
|
||||||
{
|
|
||||||
Log($"Retry {failure.TryNumber} took {Time.FormatDuration(failure.Duration)} and failed with '{failure.Exception}'. " +
|
|
||||||
$"(HTTP timeout = {Time.FormatDuration(timeSet.HttpCallTimeout())}) " +
|
|
||||||
$"Checking if node responds to debug/info...");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var debugInfo = GetDebugInfo();
|
|
||||||
if (string.IsNullOrEmpty(debugInfo.Spr))
|
|
||||||
{
|
|
||||||
Log("Did not get value debug/info response.");
|
|
||||||
Throw(failure);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log("Got valid response from debug/info.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log("Got exception from debug/info call: " + ex);
|
|
||||||
Throw(failure);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure.Duration < timeSet.HttpCallTimeout())
|
|
||||||
{
|
|
||||||
Log("Retry failed within HTTP timeout duration.");
|
|
||||||
Throw(failure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Throw(Failure failure)
|
private void Throw(Failure failure)
|
||||||
{
|
{
|
||||||
throw failure.Exception;
|
throw failure.Exception;
|
||||||
39
ProjectPlugins/CodexClient/CodexClient.csproj
Normal file
39
ProjectPlugins/CodexClient/CodexClient.csproj
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="openapi.yaml" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<OpenApiReference Include="openapi.yaml">
|
||||||
|
<CodeGenerator>NSwagCSharp</CodeGenerator>
|
||||||
|
<Namespace>CodexOpenApi</Namespace>
|
||||||
|
<ClassName></ClassName>
|
||||||
|
</OpenApiReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="7.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.18.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Framework\FileUtils\FileUtils.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Framework\Logging\Logging.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Framework\WebUtils\WebUtils.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
40
ProjectPlugins/CodexClient/CodexInstance.cs
Normal file
40
ProjectPlugins/CodexClient/CodexInstance.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using Utils;
|
||||||
|
|
||||||
|
namespace CodexClient
|
||||||
|
{
|
||||||
|
public interface ICodexInstance
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
string ImageName { get; }
|
||||||
|
DateTime StartUtc { get; }
|
||||||
|
Address DiscoveryEndpoint { get; }
|
||||||
|
Address ApiEndpoint { get; }
|
||||||
|
Address ListenEndpoint { get; }
|
||||||
|
EthAccount? EthAccount { get; }
|
||||||
|
Address? MetricsEndpoint { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CodexInstance : ICodexInstance
|
||||||
|
{
|
||||||
|
public CodexInstance(string name, string imageName, DateTime startUtc, Address discoveryEndpoint, Address apiEndpoint, Address listenEndpoint, EthAccount? ethAccount, Address? metricsEndpoint)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
ImageName = imageName;
|
||||||
|
StartUtc = startUtc;
|
||||||
|
DiscoveryEndpoint = discoveryEndpoint;
|
||||||
|
ApiEndpoint = apiEndpoint;
|
||||||
|
ListenEndpoint = listenEndpoint;
|
||||||
|
EthAccount = ethAccount;
|
||||||
|
MetricsEndpoint = metricsEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
public string ImageName { get; }
|
||||||
|
public DateTime StartUtc { get; }
|
||||||
|
public Address DiscoveryEndpoint { get; }
|
||||||
|
public Address ApiEndpoint { get; }
|
||||||
|
public Address ListenEndpoint { get; }
|
||||||
|
public EthAccount? EthAccount { get; }
|
||||||
|
public Address? MetricsEndpoint { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public enum CodexLogLevel
|
public enum CodexLogLevel
|
||||||
{
|
{
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public class CodexLogLine
|
public class CodexLogLine
|
||||||
{
|
{
|
||||||
@ -1,14 +1,11 @@
|
|||||||
using CodexPlugin.Hooks;
|
using CodexClient.Hooks;
|
||||||
using Core;
|
|
||||||
using FileUtils;
|
using FileUtils;
|
||||||
using GethPlugin;
|
|
||||||
using Logging;
|
using Logging;
|
||||||
using MetricsPlugin;
|
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public interface ICodexNode : IHasMetricsScrapeTarget, IHasEthAddress
|
public partial interface ICodexNode : IHasEthAddress
|
||||||
{
|
{
|
||||||
string GetName();
|
string GetName();
|
||||||
string GetImageName();
|
string GetImageName();
|
||||||
@ -17,10 +14,8 @@ namespace CodexPlugin
|
|||||||
string GetSpr();
|
string GetSpr();
|
||||||
DebugPeer GetDebugPeer(string peerId);
|
DebugPeer GetDebugPeer(string peerId);
|
||||||
ContentId UploadFile(TrackedFile file);
|
ContentId UploadFile(TrackedFile file);
|
||||||
ContentId UploadFile(TrackedFile file, Action<Failure> onFailure);
|
ContentId UploadFile(TrackedFile file, string contentType, string contentDisposition);
|
||||||
ContentId UploadFile(TrackedFile file, string contentType, string contentDisposition, Action<Failure> onFailure);
|
|
||||||
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
|
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
|
||||||
TrackedFile? DownloadContent(ContentId contentId, Action<Failure> onFailure, string fileLabel = "");
|
|
||||||
LocalDataset DownloadStreamless(ContentId cid);
|
LocalDataset DownloadStreamless(ContentId cid);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TODO: This will monitor the quota-used of the node until 'size' bytes are added. That's a very bad way
|
/// TODO: This will monitor the quota-used of the node until 'size' bytes are added. That's a very bad way
|
||||||
@ -54,23 +49,23 @@ namespace CodexPlugin
|
|||||||
{
|
{
|
||||||
private const string UploadFailedMessage = "Unable to store block";
|
private const string UploadFailedMessage = "Unable to store block";
|
||||||
private readonly ILog log;
|
private readonly ILog log;
|
||||||
private readonly IPluginTools tools;
|
|
||||||
private readonly ICodexNodeHooks hooks;
|
private readonly ICodexNodeHooks hooks;
|
||||||
private readonly TransferSpeeds transferSpeeds;
|
private readonly TransferSpeeds transferSpeeds;
|
||||||
private string peerId = string.Empty;
|
private string peerId = string.Empty;
|
||||||
private string nodeId = string.Empty;
|
private string nodeId = string.Empty;
|
||||||
private readonly CodexAccess codexAccess;
|
private readonly CodexAccess codexAccess;
|
||||||
|
private readonly IFileManager fileManager;
|
||||||
|
|
||||||
public CodexNode(IPluginTools tools, CodexAccess codexAccess, IMarketplaceAccess marketplaceAccess, ICodexNodeHooks hooks)
|
public CodexNode(ILog log, CodexAccess codexAccess, IFileManager fileManager, IMarketplaceAccess marketplaceAccess, ICodexNodeHooks hooks)
|
||||||
{
|
{
|
||||||
this.tools = tools;
|
|
||||||
this.codexAccess = codexAccess;
|
this.codexAccess = codexAccess;
|
||||||
|
this.fileManager = fileManager;
|
||||||
Marketplace = marketplaceAccess;
|
Marketplace = marketplaceAccess;
|
||||||
this.hooks = hooks;
|
this.hooks = hooks;
|
||||||
Version = new DebugInfoVersion();
|
Version = new DebugInfoVersion();
|
||||||
transferSpeeds = new TransferSpeeds();
|
transferSpeeds = new TransferSpeeds();
|
||||||
|
|
||||||
log = new LogPrefixer(tools.GetLog(), $"{GetName()} ");
|
this.log = new LogPrefixer(log, $"{GetName()} ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Awake()
|
public void Awake()
|
||||||
@ -156,15 +151,10 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
public ContentId UploadFile(TrackedFile file)
|
public ContentId UploadFile(TrackedFile file)
|
||||||
{
|
{
|
||||||
return UploadFile(file, DoNothing);
|
return UploadFile(file, "application/octet-stream", $"attachment; filename=\"{Path.GetFileName(file.Filename)}\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentId UploadFile(TrackedFile file, Action<Failure> onFailure)
|
public ContentId UploadFile(TrackedFile file, string contentType, string contentDisposition)
|
||||||
{
|
|
||||||
return UploadFile(file, "application/octet-stream", $"attachment; filename=\"{Path.GetFileName(file.Filename)}\"", onFailure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContentId UploadFile(TrackedFile file, string contentType, string contentDisposition, Action<Failure> onFailure)
|
|
||||||
{
|
{
|
||||||
using var fileStream = File.OpenRead(file.Filename);
|
using var fileStream = File.OpenRead(file.Filename);
|
||||||
var uniqueId = Guid.NewGuid().ToString();
|
var uniqueId = Guid.NewGuid().ToString();
|
||||||
@ -176,7 +166,7 @@ namespace CodexPlugin
|
|||||||
var logMessage = $"Uploading file {file.Describe()} with contentType: '{input.ContentType}' and disposition: '{input.ContentDisposition}'...";
|
var logMessage = $"Uploading file {file.Describe()} with contentType: '{input.ContentType}' and disposition: '{input.ContentDisposition}'...";
|
||||||
var measurement = Stopwatch.Measure(log, logMessage, () =>
|
var measurement = Stopwatch.Measure(log, logMessage, () =>
|
||||||
{
|
{
|
||||||
return codexAccess.UploadFile(input, onFailure);
|
return codexAccess.UploadFile(input);
|
||||||
});
|
});
|
||||||
|
|
||||||
var response = measurement.Value;
|
var response = measurement.Value;
|
||||||
@ -194,17 +184,12 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
public TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "")
|
public TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "")
|
||||||
{
|
{
|
||||||
return DownloadContent(contentId, DoNothing, fileLabel);
|
var file = fileManager.CreateEmptyFile(fileLabel);
|
||||||
}
|
|
||||||
|
|
||||||
public TrackedFile? DownloadContent(ContentId contentId, Action<Failure> onFailure, string fileLabel = "")
|
|
||||||
{
|
|
||||||
var file = tools.GetFileManager().CreateEmptyFile(fileLabel);
|
|
||||||
hooks.OnFileDownloading(contentId);
|
hooks.OnFileDownloading(contentId);
|
||||||
Log($"Downloading '{contentId}'...");
|
Log($"Downloading '{contentId}'...");
|
||||||
|
|
||||||
var logMessage = $"Downloaded '{contentId}' to '{file.Filename}'";
|
var logMessage = $"Downloaded '{contentId}' to '{file.Filename}'";
|
||||||
var measurement = Stopwatch.Measure(log, logMessage, () => DownloadToFile(contentId.Id, file, onFailure));
|
var measurement = Stopwatch.Measure(log, logMessage, () => DownloadToFile(contentId.Id, file));
|
||||||
|
|
||||||
var size = file.GetFilesize();
|
var size = file.GetFilesize();
|
||||||
transferSpeeds.AddDownloadSample(size, measurement);
|
transferSpeeds.AddDownloadSample(size, measurement);
|
||||||
@ -337,20 +322,20 @@ namespace CodexPlugin
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DownloadToFile(string contentId, TrackedFile file, Action<Failure> onFailure)
|
private void DownloadToFile(string contentId, TrackedFile file)
|
||||||
{
|
{
|
||||||
using var fileStream = File.OpenWrite(file.Filename);
|
using var fileStream = File.OpenWrite(file.Filename);
|
||||||
var timeout = tools.TimeSet.HttpCallTimeout();
|
var timeout = TimeSpan.FromMinutes(2.0); // todo: make this user-controllable.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Type of stream generated by openAPI client does not support timeouts.
|
// Type of stream generated by openAPI client does not support timeouts.
|
||||||
var start = DateTime.UtcNow;
|
var start = DateTime.UtcNow;
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
var downloadTask = Task.Run((Action)(() =>
|
var downloadTask = Task.Run(() =>
|
||||||
{
|
{
|
||||||
using var downloadStream = this.codexAccess.DownloadFile(contentId, onFailure);
|
using var downloadStream = codexAccess.DownloadFile(contentId);
|
||||||
downloadStream.CopyTo((Stream)fileStream);
|
downloadStream.CopyTo(fileStream);
|
||||||
}), cts.Token);
|
}, cts.Token);
|
||||||
|
|
||||||
while (DateTime.UtcNow - start < timeout)
|
while (DateTime.UtcNow - start < timeout)
|
||||||
{
|
{
|
||||||
@ -411,9 +396,5 @@ namespace CodexPlugin
|
|||||||
{
|
{
|
||||||
log.Log(msg);
|
log.Log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoNothing(Failure failure)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public class DebugInfo
|
public class DebugInfo
|
||||||
{
|
{
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public static class CodexUtils
|
public static class CodexUtils
|
||||||
{
|
{
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using GethPlugin;
|
using Utils;
|
||||||
using Utils;
|
|
||||||
|
|
||||||
namespace CodexPlugin.Hooks
|
namespace CodexClient.Hooks
|
||||||
{
|
{
|
||||||
public interface ICodexHooksProvider
|
public interface ICodexHooksProvider
|
||||||
{
|
{
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using GethPlugin;
|
using Utils;
|
||||||
using Utils;
|
|
||||||
|
|
||||||
namespace CodexPlugin.Hooks
|
namespace CodexClient.Hooks
|
||||||
{
|
{
|
||||||
public interface ICodexNodeHooks
|
public interface ICodexNodeHooks
|
||||||
{
|
{
|
||||||
@ -1,10 +1,8 @@
|
|||||||
using CodexContractsPlugin;
|
using Newtonsoft.Json.Linq;
|
||||||
using CodexOpenApi;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public class Mapper
|
public class Mapper
|
||||||
{
|
{
|
||||||
@ -80,12 +78,12 @@ namespace CodexPlugin
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public StorageAvailability[] Map(ICollection<SalesAvailabilityREAD> availabilities)
|
public StorageAvailability[] Map(ICollection<CodexOpenApi.SalesAvailabilityREAD> availabilities)
|
||||||
{
|
{
|
||||||
return availabilities.Select(a => Map(a)).ToArray();
|
return availabilities.Select(a => Map(a)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StorageAvailability Map(SalesAvailabilityREAD availability)
|
public StorageAvailability Map(CodexOpenApi.SalesAvailabilityREAD availability)
|
||||||
{
|
{
|
||||||
return new StorageAvailability
|
return new StorageAvailability
|
||||||
(
|
(
|
||||||
@ -142,7 +140,7 @@ namespace CodexPlugin
|
|||||||
// };
|
// };
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public CodexSpace Map(Space space)
|
public CodexSpace Map(CodexOpenApi.Space space)
|
||||||
{
|
{
|
||||||
return new CodexSpace
|
return new CodexSpace
|
||||||
{
|
{
|
||||||
@ -153,7 +151,7 @@ namespace CodexPlugin
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private DebugInfoVersion Map(CodexVersion obj)
|
private DebugInfoVersion Map(CodexOpenApi.CodexVersion obj)
|
||||||
{
|
{
|
||||||
return new DebugInfoVersion
|
return new DebugInfoVersion
|
||||||
{
|
{
|
||||||
@ -162,7 +160,7 @@ namespace CodexPlugin
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private DebugInfoTable Map(PeersTable obj)
|
private DebugInfoTable Map(CodexOpenApi.PeersTable obj)
|
||||||
{
|
{
|
||||||
return new DebugInfoTable
|
return new DebugInfoTable
|
||||||
{
|
{
|
||||||
@ -171,7 +169,7 @@ namespace CodexPlugin
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private DebugInfoTableNode Map(Node? token)
|
private DebugInfoTableNode Map(CodexOpenApi.Node? token)
|
||||||
{
|
{
|
||||||
if (token == null) return new DebugInfoTableNode();
|
if (token == null) return new DebugInfoTableNode();
|
||||||
return new DebugInfoTableNode
|
return new DebugInfoTableNode
|
||||||
@ -184,7 +182,7 @@ namespace CodexPlugin
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private DebugInfoTableNode[] Map(ICollection<Node> nodes)
|
private DebugInfoTableNode[] Map(ICollection<CodexOpenApi.Node> nodes)
|
||||||
{
|
{
|
||||||
if (nodes == null || nodes.Count == 0)
|
if (nodes == null || nodes.Count == 0)
|
||||||
{
|
{
|
||||||
@ -1,8 +1,8 @@
|
|||||||
using CodexPlugin.Hooks;
|
using CodexClient.Hooks;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public interface IMarketplaceAccess
|
public interface IMarketplaceAccess
|
||||||
{
|
{
|
||||||
@ -1,8 +1,7 @@
|
|||||||
using CodexContractsPlugin;
|
using Logging;
|
||||||
using Logging;
|
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public class StoragePurchaseRequest
|
public class StoragePurchaseRequest
|
||||||
{
|
{
|
||||||
11
ProjectPlugins/CodexClient/ProcessControl.cs
Normal file
11
ProjectPlugins/CodexClient/ProcessControl.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Logging;
|
||||||
|
|
||||||
|
namespace CodexClient
|
||||||
|
{
|
||||||
|
public interface IProcessControl
|
||||||
|
{
|
||||||
|
void Stop(ICodexInstance instance, bool waitTillStopped);
|
||||||
|
IDownloadedLog DownloadLog(ICodexInstance instance, LogFile file);
|
||||||
|
void DeleteDataDirFolder(ICodexInstance instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,9 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexClient.Hooks;
|
||||||
using CodexPlugin.Hooks;
|
|
||||||
using GethPlugin;
|
|
||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public interface IStoragePurchaseContract
|
public interface IStoragePurchaseContract
|
||||||
{
|
{
|
||||||
@ -14,7 +12,7 @@ namespace CodexPlugin
|
|||||||
ContentId ContentId { get; }
|
ContentId ContentId { get; }
|
||||||
void WaitForStorageContractSubmitted();
|
void WaitForStorageContractSubmitted();
|
||||||
void WaitForStorageContractStarted();
|
void WaitForStorageContractStarted();
|
||||||
void WaitForStorageContractFinished(ICodexContracts contracts);
|
void WaitForStorageContractFinished();
|
||||||
void WaitForContractFailed();
|
void WaitForContractFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ namespace CodexPlugin
|
|||||||
AssertDuration(SubmittedToStarted, timeout, nameof(SubmittedToStarted));
|
AssertDuration(SubmittedToStarted, timeout, nameof(SubmittedToStarted));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitForStorageContractFinished(ICodexContracts contracts)
|
public void WaitForStorageContractFinished()
|
||||||
{
|
{
|
||||||
if (!contractStartedUtc.HasValue)
|
if (!contractStartedUtc.HasValue)
|
||||||
{
|
{
|
||||||
@ -77,13 +75,6 @@ namespace CodexPlugin
|
|||||||
contractFinishedUtc = DateTime.UtcNow;
|
contractFinishedUtc = DateTime.UtcNow;
|
||||||
LogFinishedDuration();
|
LogFinishedDuration();
|
||||||
AssertDuration(SubmittedToFinished, timeout, nameof(SubmittedToFinished));
|
AssertDuration(SubmittedToFinished, timeout, nameof(SubmittedToFinished));
|
||||||
|
|
||||||
contracts.WaitUntilNextPeriod();
|
|
||||||
contracts.WaitUntilNextPeriod();
|
|
||||||
|
|
||||||
var blocks = 3;
|
|
||||||
Log($"Waiting {blocks} blocks for nodes to process payouts...");
|
|
||||||
Thread.Sleep(GethContainerRecipe.BlockInterval * blocks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitForContractFailed()
|
public void WaitForContractFailed()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexClient
|
||||||
{
|
{
|
||||||
public interface ITransferSpeeds
|
public interface ITransferSpeeds
|
||||||
{
|
{
|
||||||
@ -1,47 +1,10 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using GethPlugin;
|
|
||||||
using KubernetesWorkflow.Types;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
public interface ICodexInstance
|
|
||||||
{
|
|
||||||
string Name { get; }
|
|
||||||
string ImageName { get; }
|
|
||||||
DateTime StartUtc { get; }
|
|
||||||
Address DiscoveryEndpoint { get; }
|
|
||||||
Address ApiEndpoint { get; }
|
|
||||||
Address ListenEndpoint { get; }
|
|
||||||
EthAccount? EthAccount { get; }
|
|
||||||
Address? MetricsEndpoint { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CodexInstance : ICodexInstance
|
|
||||||
{
|
|
||||||
public CodexInstance(string name, string imageName, DateTime startUtc, Address discoveryEndpoint, Address apiEndpoint, Address listenEndpoint, EthAccount? ethAccount, Address? metricsEndpoint)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
ImageName = imageName;
|
|
||||||
StartUtc = startUtc;
|
|
||||||
DiscoveryEndpoint = discoveryEndpoint;
|
|
||||||
ApiEndpoint = apiEndpoint;
|
|
||||||
ListenEndpoint = listenEndpoint;
|
|
||||||
EthAccount = ethAccount;
|
|
||||||
MetricsEndpoint = metricsEndpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
public string ImageName { get; }
|
|
||||||
public DateTime StartUtc { get; }
|
|
||||||
public Address DiscoveryEndpoint { get; }
|
|
||||||
public Address ApiEndpoint { get; }
|
|
||||||
public Address ListenEndpoint { get; }
|
|
||||||
public EthAccount? EthAccount { get; }
|
|
||||||
public Address? MetricsEndpoint { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CodexInstanceContainerExtension
|
public static class CodexInstanceContainerExtension
|
||||||
{
|
{
|
||||||
public static ICodexInstance CreateFromPod(RunningPod pod)
|
public static ICodexInstance CreateFromPod(RunningPod pod)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
@ -6,14 +6,6 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="openapi.yaml" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<OpenApiReference Include="openapi.yaml" CodeGenerator="NSwagCSharp" Namespace="CodexOpenApi" ClassName="CodexApi" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="7.0.2">
|
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="7.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
@ -30,6 +22,7 @@
|
|||||||
<ProjectReference Include="..\..\Framework\Core\Core.csproj" />
|
<ProjectReference Include="..\..\Framework\Core\Core.csproj" />
|
||||||
<ProjectReference Include="..\..\Framework\KubernetesWorkflow\KubernetesWorkflow.csproj" />
|
<ProjectReference Include="..\..\Framework\KubernetesWorkflow\KubernetesWorkflow.csproj" />
|
||||||
<ProjectReference Include="..\..\Framework\OverwatchTranscript\OverwatchTranscript.csproj" />
|
<ProjectReference Include="..\..\Framework\OverwatchTranscript\OverwatchTranscript.csproj" />
|
||||||
|
<ProjectReference Include="..\CodexClient\CodexClient.csproj" />
|
||||||
<ProjectReference Include="..\CodexContractsPlugin\CodexContractsPlugin.csproj" />
|
<ProjectReference Include="..\CodexContractsPlugin\CodexContractsPlugin.csproj" />
|
||||||
<ProjectReference Include="..\GethPlugin\GethPlugin.csproj" />
|
<ProjectReference Include="..\GethPlugin\GethPlugin.csproj" />
|
||||||
<ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" />
|
<ProjectReference Include="..\MetricsPlugin\MetricsPlugin.csproj" />
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using CodexPlugin.Hooks;
|
using CodexPlugin.Hooks;
|
||||||
using Core;
|
using Core;
|
||||||
using GethPlugin;
|
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
using KubernetesWorkflow.Types;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using CodexPlugin.Hooks;
|
using CodexPlugin.Hooks;
|
||||||
using GethPlugin;
|
|
||||||
using OverwatchTranscript;
|
using OverwatchTranscript;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
using Logging;
|
|
||||||
|
|
||||||
namespace CodexPlugin
|
|
||||||
{
|
|
||||||
public interface IProcessControl
|
|
||||||
{
|
|
||||||
void Stop(ICodexInstance instance, bool waitTillStopped);
|
|
||||||
IDownloadedLog DownloadLog(ICodexInstance instance, LogFile file);
|
|
||||||
void DeleteDataDirFolder(ICodexInstance instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//public void DeleteDataDirFolder()
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var dataDirVar = container.Recipe.EnvVars.Single(e => e.Name == "CODEX_DATA_DIR");
|
|
||||||
// var dataDir = dataDirVar.Value;
|
|
||||||
// var workflow = tools.CreateWorkflow();
|
|
||||||
// workflow.ExecuteCommand(container, "rm", "-Rfv", $"/codex/{dataDir}/repo");
|
|
||||||
// log.Log("Deleted repo folder.");
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// log.Log("Unable to delete repo folder: " + e);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -12,11 +12,12 @@ public static class Program
|
|||||||
{
|
{
|
||||||
Console.WriteLine("Injecting hash of 'openapi.yaml'...");
|
Console.WriteLine("Injecting hash of 'openapi.yaml'...");
|
||||||
|
|
||||||
var root = FindCodexPluginFolder();
|
var pluginRoot = FindCodexPluginFolder();
|
||||||
Console.WriteLine("Located CodexPlugin: " + root);
|
var clientRoot = FindCodexClientFolder();
|
||||||
var openApiFile = Path.Combine(root, "openapi.yaml");
|
Console.WriteLine("Located CodexPlugin: " + pluginRoot);
|
||||||
var clientFile = Path.Combine(root, "obj", "openapiClient.cs");
|
var openApiFile = Path.Combine(pluginRoot, "openapi.yaml");
|
||||||
var targetFile = Path.Combine(root, "ApiChecker.cs");
|
var clientFile = Path.Combine(clientRoot, "obj", "openapiClient.cs");
|
||||||
|
var targetFile = Path.Combine(pluginRoot, "ApiChecker.cs");
|
||||||
|
|
||||||
// Force client rebuild by deleting previous artifact.
|
// Force client rebuild by deleting previous artifact.
|
||||||
File.Delete(clientFile);
|
File.Delete(clientFile);
|
||||||
@ -46,6 +47,13 @@ public static class Program
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string FindCodexClientFolder()
|
||||||
|
{
|
||||||
|
var folder = Path.Combine(PluginPathUtils.ProjectPluginsDir, "CodexClient");
|
||||||
|
if (!Directory.Exists(folder)) throw new Exception("CodexClient folder not found. Expected: " + folder);
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
private static string CreateHash(string openApiFile)
|
private static string CreateHash(string openApiFile)
|
||||||
{
|
{
|
||||||
var file = File.ReadAllText(openApiFile);
|
var file = File.ReadAllText(openApiFile);
|
||||||
|
|||||||
@ -1,20 +1,11 @@
|
|||||||
using Nethereum.Hex.HexConvertors.Extensions;
|
using Nethereum.Hex.HexConvertors.Extensions;
|
||||||
using Nethereum.Web3.Accounts;
|
using Nethereum.Web3.Accounts;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
namespace GethPlugin
|
namespace GethPlugin
|
||||||
{
|
{
|
||||||
[Serializable]
|
public static class EthAccountGenerator
|
||||||
public class EthAccount
|
|
||||||
{
|
{
|
||||||
public EthAccount(EthAddress ethAddress, string privateKey)
|
|
||||||
{
|
|
||||||
EthAddress = ethAddress;
|
|
||||||
PrivateKey = privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EthAddress EthAddress { get; }
|
|
||||||
public string PrivateKey { get; }
|
|
||||||
|
|
||||||
public static EthAccount GenerateNew()
|
public static EthAccount GenerateNew()
|
||||||
{
|
{
|
||||||
var ecKey = Nethereum.Signer.EthECKey.GenerateKey();
|
var ecKey = Nethereum.Signer.EthECKey.GenerateKey();
|
||||||
@ -24,10 +15,5 @@ namespace GethPlugin
|
|||||||
|
|
||||||
return new EthAccount(ethAddress, account.PrivateKey);
|
return new EthAccount(ethAddress, account.PrivateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return EthAddress.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexClient;
|
||||||
|
using CodexContractsPlugin;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexClient;
|
||||||
|
using CodexContractsPlugin;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -37,6 +38,14 @@ namespace CodexReleaseTests.MarketTests
|
|||||||
|
|
||||||
All(requests, r => r.WaitForStorageContractFinished(GetContracts()));
|
All(requests, r => r.WaitForStorageContractFinished(GetContracts()));
|
||||||
|
|
||||||
|
// todo: removed from codexclient:
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
|
||||||
|
//var blocks = 3;
|
||||||
|
//Log($"Waiting {blocks} blocks for nodes to process payouts...");
|
||||||
|
//Thread.Sleep(GethContainerRecipe.BlockInterval * blocks);
|
||||||
|
|
||||||
// todo:
|
// todo:
|
||||||
//AssertClientHasPaidForContract(pricePerSlotPerSecond, client, request, hosts);
|
//AssertClientHasPaidForContract(pricePerSlotPerSecond, client, request, hosts);
|
||||||
//AssertHostsWerePaidForContract(pricePerSlotPerSecond, request, hosts);
|
//AssertHostsWerePaidForContract(pricePerSlotPerSecond, request, hosts);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using GethPlugin;
|
|
||||||
using MetricsPlugin;
|
using MetricsPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexClient;
|
||||||
|
using CodexContractsPlugin;
|
||||||
using CodexContractsPlugin.Marketplace;
|
using CodexContractsPlugin.Marketplace;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using FileUtils;
|
using FileUtils;
|
||||||
@ -109,6 +110,14 @@ namespace CodexTests.BasicTests
|
|||||||
|
|
||||||
purchaseContract.WaitForStorageContractFinished(contracts);
|
purchaseContract.WaitForStorageContractFinished(contracts);
|
||||||
|
|
||||||
|
// todo: removed from codexclient:
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
|
||||||
|
//var blocks = 3;
|
||||||
|
//Log($"Waiting {blocks} blocks for nodes to process payouts...");
|
||||||
|
//Thread.Sleep(GethContainerRecipe.BlockInterval * blocks);
|
||||||
|
|
||||||
AssertBalance(contracts, client, Is.LessThan(clientInitialBalance), "Buyer was not charged for storage.");
|
AssertBalance(contracts, client, Is.LessThan(clientInitialBalance), "Buyer was not charged for storage.");
|
||||||
Assert.That(contracts.GetRequestState(request), Is.EqualTo(RequestState.Finished));
|
Assert.That(contracts.GetRequestState(request), Is.EqualTo(RequestState.Finished));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexClient;
|
||||||
|
using CodexContractsPlugin;
|
||||||
using CodexDiscordBotPlugin;
|
using CodexDiscordBotPlugin;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using Core;
|
using Core;
|
||||||
@ -46,6 +47,15 @@ namespace CodexTests.UtilityTests
|
|||||||
var purchaseContract = ClientPurchasesStorage(client);
|
var purchaseContract = ClientPurchasesStorage(client);
|
||||||
purchaseContract.WaitForStorageContractStarted();
|
purchaseContract.WaitForStorageContractStarted();
|
||||||
purchaseContract.WaitForStorageContractFinished(contracts);
|
purchaseContract.WaitForStorageContractFinished(contracts);
|
||||||
|
|
||||||
|
// todo: removed from codexclient:
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
//contracts.WaitUntilNextPeriod();
|
||||||
|
|
||||||
|
//var blocks = 3;
|
||||||
|
//Log($"Waiting {blocks} blocks for nodes to process payouts...");
|
||||||
|
//Thread.Sleep(GethContainerRecipe.BlockInterval * blocks);
|
||||||
|
|
||||||
Thread.Sleep(rewarderInterval * 3);
|
Thread.Sleep(rewarderInterval * 3);
|
||||||
|
|
||||||
apiCalls.Stop();
|
apiCalls.Stop();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using GethPlugin;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
namespace KeyMaker.Controllers
|
namespace KeyMaker.Controllers
|
||||||
{
|
{
|
||||||
|
|||||||
@ -82,6 +82,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExperimentalTests", "Tests\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockchainUtils", "Framework\BlockchainUtils\BlockchainUtils.csproj", "{4648B5AA-A0A7-44BA-89BC-2FD57370943C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockchainUtils", "Framework\BlockchainUtils\BlockchainUtils.csproj", "{4648B5AA-A0A7-44BA-89BC-2FD57370943C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodexClient", "ProjectPlugins\CodexClient\CodexClient.csproj", "{9AF12703-29AF-416D-9781-204223D6D0E5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebUtils", "Framework\WebUtils\WebUtils.csproj", "{372C9E5D-5453-4D45-9948-E9324E21AD65}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -220,6 +224,14 @@ Global
|
|||||||
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4648B5AA-A0A7-44BA-89BC-2FD57370943C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9AF12703-29AF-416D-9781-204223D6D0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9AF12703-29AF-416D-9781-204223D6D0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9AF12703-29AF-416D-9781-204223D6D0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9AF12703-29AF-416D-9781-204223D6D0E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{372C9E5D-5453-4D45-9948-E9324E21AD65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{372C9E5D-5453-4D45-9948-E9324E21AD65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{372C9E5D-5453-4D45-9948-E9324E21AD65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{372C9E5D-5453-4D45-9948-E9324E21AD65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -258,6 +270,8 @@ Global
|
|||||||
{639A0603-4E80-465B-BB59-AB02F1DEEF5A} = {88C2A621-8A98-4D07-8625-7900FC8EF89E}
|
{639A0603-4E80-465B-BB59-AB02F1DEEF5A} = {88C2A621-8A98-4D07-8625-7900FC8EF89E}
|
||||||
{BA7369CD-7C2F-4075-8E35-98BCC19EE203} = {88C2A621-8A98-4D07-8625-7900FC8EF89E}
|
{BA7369CD-7C2F-4075-8E35-98BCC19EE203} = {88C2A621-8A98-4D07-8625-7900FC8EF89E}
|
||||||
{4648B5AA-A0A7-44BA-89BC-2FD57370943C} = {81AE04BC-CBFA-4E6F-B039-8208E9AFAAE7}
|
{4648B5AA-A0A7-44BA-89BC-2FD57370943C} = {81AE04BC-CBFA-4E6F-B039-8208E9AFAAE7}
|
||||||
|
{9AF12703-29AF-416D-9781-204223D6D0E5} = {8F1F1C2A-E313-4E0C-BE40-58FB0BA91124}
|
||||||
|
{372C9E5D-5453-4D45-9948-E9324E21AD65} = {81AE04BC-CBFA-4E6F-B039-8208E9AFAAE7}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {237BF0AA-9EC4-4659-AD9A-65DEB974250C}
|
SolutionGuid = {237BF0AA-9EC4-4659-AD9A-65DEB974250C}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user