Skip to content

Commit

Permalink
Merge pull request #225 from Elenpay/show-user-channel-opening-failur…
Browse files Browse the repository at this point in the history
…e-reason

Show user channel opening failure reason
  • Loading branch information
RodriFS authored Jul 6, 2023
2 parents 8754aeb + 8e82e9b commit 598314c
Show file tree
Hide file tree
Showing 12 changed files with 1,406 additions and 4 deletions.
17 changes: 14 additions & 3 deletions src/Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
* along with this program. If not, see http://www.gnu.org/licenses/.
*/

using System.Text.Json;
using FundsManager.Data.Models;
using FundsManager.Helpers;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

Expand Down Expand Up @@ -51,12 +53,21 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Node>().HasIndex(x => x.PubKey).IsUnique();
modelBuilder.Entity<Node>().HasIndex(x => x.Name).IsUnique();
modelBuilder.Entity<Wallet>().HasIndex(x => new {x.InternalWalletSubDerivationPath, x.InternalWalletMasterFingerprint}).IsUnique();

//There should be only one Liquidity Rule per Channel
modelBuilder.Entity<LiquidityRule>().HasIndex(x => x.ChannelId).IsUnique();

modelBuilder.Entity<ApplicationUser>().HasIndex(x => x.NormalizedUserName).IsUnique();

modelBuilder.Entity<ChannelStatusLog>().HasNoKey();

modelBuilder.Entity<ChannelOperationRequest>()
.Property(e => e.StatusLogs)
.HasConversion(
v => JsonSerializer.Serialize(v, new JsonSerializerOptions()),
v => JsonSerializer.Deserialize<List<ChannelStatusLog>>(v, new JsonSerializerOptions())
);

base.OnModelCreating(modelBuilder);
}

Expand All @@ -81,7 +92,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
public DbSet<InternalWallet> InternalWallets { get; set; }

public DbSet<FMUTXO> FMUTXOs { get; set; }

public DbSet<LiquidityRule> LiquidityRules { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/Data/Models/ChannelOperationRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
*/

using System.ComponentModel.DataAnnotations.Schema;
using FundsManager.Helpers;
using NBitcoin;
using System.Text.Json;

namespace FundsManager.Data.Models
{
Expand Down Expand Up @@ -101,6 +103,9 @@ public decimal Amount

public decimal? FeeRate { get; set; }

[Column(TypeName = "jsonb")]
public List<ChannelStatusLog> StatusLogs { get; set; } = new();

#region Relationships

public ICollection<ChannelOperationRequestPSBT> ChannelOperationRequestPsbts { get; set; }
Expand Down
40 changes: 40 additions & 0 deletions src/Helpers/ChannelStatusLog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Text.Json.Serialization;

namespace FundsManager.Helpers;

public class ChannelStatusLog
{
public DateTime DateTime { get; set; }
public LogLevel Level { get; set; }
public string Description { get; set; }

[JsonConstructor]
public ChannelStatusLog(DateTime dateTime, LogLevel level, string description)
{
DateTime = dateTime;
Level = level;
Description = description;
}

public ChannelStatusLog(LogLevel level, string description)
{
DateTime = DateTime.Now;
Level = level;
Description = description;
}

public static ChannelStatusLog Info(string description)
{
return new ChannelStatusLog(LogLevel.Information, description);
}

public static ChannelStatusLog Error(string description)
{
return new ChannelStatusLog(LogLevel.Error, description);
}

public static ChannelStatusLog Warning(string description)
{
return new ChannelStatusLog(LogLevel.Warning, description);
}
}
10 changes: 10 additions & 0 deletions src/Helpers/CustomExceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,14 @@ public NBXplorerNotFullySyncedException(): base("Error, nbxplorer not fully sync
public class ShowToUserException : Exception
{
public ShowToUserException(string? message): base(message) {}
}

public class PeerNotOnlineException : Exception
{
public PeerNotOnlineException(string? message = null): base(message) {}
}

public class RemoteCanceledFundingException : Exception
{
public RemoteCanceledFundingException(string? message = null): base(message) {}
}
23 changes: 23 additions & 0 deletions src/Helpers/JobTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,29 @@ public static async Task OnFail(IJobExecutionContext context, Func<Task> callbac
await callback();
}
}

/// <summary>
/// Get the next interval time
/// </summary>
/// <param name="context">The execution context of the job</param>
public static int? GetNextInterval(IJobExecutionContext context)
{
var data = context.JobDetail.JobDataMap;
var intervals = data.Get("intervalListInMinutes") as int[];
if (intervals == null)
{
throw new Exception("No interval list found, make sure you're using the RetriableJob class");
};

var trigger = context.Trigger as SimpleTriggerImpl;

if (trigger!.TimesTriggered <= intervals.Length)
{
return intervals[trigger!.TimesTriggered - 1];
}

return null;
}
}

public class JobAndTrigger
Expand Down
42 changes: 42 additions & 0 deletions src/Jobs/ChannelOpenJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ await RetriableJob.Execute(context, async () =>
}
catch (Exception e)
{
var shouldRetry = await LogToChannelRequest(openRequestId, e, context);

await RetriableJob.OnFail(context, async () =>
{
var request = await _channelOperationRequestRepository.GetById(openRequestId);
Expand All @@ -68,9 +70,49 @@ await RetriableJob.OnFail(context, async () =>
});

_logger.LogError(e, "Error on {JobName}", nameof(ChannelOpenJob));
if (!shouldRetry)
{
await context.Scheduler.DeleteJob(context.JobDetail.Key, context.CancellationToken);
}
throw new JobExecutionException(e, false);
}

_logger.LogInformation("{JobName} ended", nameof(ChannelOpenJob));
}

private async Task<bool> LogToChannelRequest(int openRequestId, Exception e, IJobExecutionContext context)
{
try
{
var request = await _channelOperationRequestRepository.GetById(openRequestId);
if (e is PeerNotOnlineException or RemoteCanceledFundingException)
{
request.StatusLogs.Add(ChannelStatusLog.Error(e.Message));
}
else
{
request.StatusLogs.Add(ChannelStatusLog.Error("Unexpected exception trying to open channel"));
}

if (e is RemoteCanceledFundingException)
{
request.Status = ChannelOperationRequestStatus.Failed;
_channelOperationRequestRepository.Update(request);
return false;
}

var nextRetry = RetriableJob.GetNextInterval(context);
if (nextRetry != null)
{
request.StatusLogs.Add(ChannelStatusLog.Info($"Next retry in {nextRetry} minutes"));
}
_channelOperationRequestRepository.Update(request);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error logging to channel request");
}

return true;
}
}
Loading

0 comments on commit 598314c

Please sign in to comment.