Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
DeployImage:
runs-on: ubuntu-latest
env:
ResQueueImageVersion: "1.2.0"
ResQueueImageVersion: "1.3.0"
DockerRegistry: ghcr.io
DockerRepository: filipbekic01/resqueue
steps:
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [v1.3.0] - 2025-01-09

### Added

- Topics table view with filters
- Recurring job indicator in table view

### Changed

- One click less for auto-refresh action
- JSON view uses mono font now
- Dark theme message colors
- Sticky-top actions when scroll is present

### Fixed

- Queue messages count invalidation on refresh

## [v1.2.0] - 2025-01-05

### Added
Expand Down
9 changes: 9 additions & 0 deletions backend/ResQueue/ResQueue/Dtos/Messages/SubscriptionDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ResQueue.Dtos.Messages;

public record SubscriptionDto(
string TopicName,
string DestinationType,
string DestinationName,
int SubscriptionType,
string RoutingKey
);
22 changes: 22 additions & 0 deletions backend/ResQueue/ResQueue/Endpoints/SubscriptionsEndpoints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using ResQueue.Features.Subscriptions.GetSubscriptions;

namespace ResQueue.Endpoints;

public static class SubscriptionsEndpoints
{
public static void MapSubscriptionsEndpoints(this IEndpointRouteBuilder routes)
{
RouteGroupBuilder group = routes.MapGroup("subscriptions");

group.MapGet("",
async (IGetSubscriptionsFeature feature) =>
{
var result = await feature.ExecuteAsync(new GetSubscriptionsRequest(
));

return result.IsSuccess
? Results.Ok(result.Value!.Subscriptions)
: Results.Problem(result.Problem!);
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Dapper;
using Microsoft.Extensions.Options;
using ResQueue.Dtos.Messages;
using ResQueue.Enums;
using ResQueue.Factories;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Dapper;
using ResQueue.Dtos.Messages;
using ResQueue.Enums;
using ResQueue.Factories;
using ResQueue.Providers.DbConnectionProvider;

namespace ResQueue.Features.Subscriptions.GetSubscriptions;

public record GetSubscriptionsRequest();

public record GetSubscriptionsResponse(List<SubscriptionDto> Subscriptions);

public class GetSubscriptionsFeature(
IDatabaseConnectionFactory connectionFactory,
IDbConnectionProvider conn
) : IGetSubscriptionsFeature
{
public async Task<OperationResult<GetSubscriptionsResponse>> ExecuteAsync(GetSubscriptionsRequest request)
{
await using var connection = connectionFactory.CreateConnection();

var subscriptions = await connection.QueryAsync<SubscriptionDto>(GetSqlQueryText());

return OperationResult<GetSubscriptionsResponse>.Success(new GetSubscriptionsResponse(
Subscriptions: subscriptions.ToList()
));
}

private string GetSqlQueryText()
{
return conn.SqlEngine switch
{
ResQueueSqlEngine.Postgres => $"""
SELECT
s.topic_name AS TopicName,
s.destination_type AS DestinationType,
s.destination_name AS DestinationName,
s.subscription_type AS SubscriptionType,
s.routing_key AS RoutingKey
FROM {conn.Schema}.subscriptions s
""",
ResQueueSqlEngine.SqlServer => $"""
SELECT
s.TopicName,
s.DestinationType,
s.DestinationName,
s.SubscriptionType,
s.RoutingKey
FROM {conn.Schema}.Subscriptions s
""",
_ => throw new NotSupportedException("Unsupported SQL Engine")
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ResQueue.Features.Subscriptions.GetSubscriptions;

public interface IGetSubscriptionsFeature
{
Task<OperationResult<GetSubscriptionsResponse>> ExecuteAsync(GetSubscriptionsRequest request);
}
2 changes: 1 addition & 1 deletion backend/ResQueue/ResQueue/ResQueue.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<!-- NuGet package properties -->
<PackageId>ResQueue.MassTransit</PackageId>
<Version>1.2.0</Version>
<Version>1.3.0</Version>
<Authors>Filip Bekić, Miroljub Tomić</Authors>
<Company>ResQueue</Company>
<Description>MassTransit SQL Transport Web UI</Description>
Expand Down
3 changes: 3 additions & 0 deletions backend/ResQueue/ResQueue/ResQueueExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using ResQueue.Features.Messages.PurgeQueue;
using ResQueue.Features.Messages.RequeueMessages;
using ResQueue.Features.Messages.RequeueSpecificMessages;
using ResQueue.Features.Subscriptions.GetSubscriptions;
using ResQueue.Providers.DbConnectionProvider;

namespace ResQueue;
Expand Down Expand Up @@ -36,6 +37,7 @@ public static IServiceCollection AddResQueue(this IServiceCollection services,
services.AddTransient<IGetMessagesFeature, GetMessagesFeature>();
services.AddTransient<IGetSingleMessageFeature, GetSingleMessageFeature>();
services.AddTransient<IPurgeQueueFeature, PurgeQueueFeature>();
services.AddTransient<IGetSubscriptionsFeature, GetSubscriptionsFeature>();

return services;
}
Expand Down Expand Up @@ -88,6 +90,7 @@ public static IApplicationBuilder UseResQueue(this WebApplication app, string pr
api.MapQueueEndpoints();
api.MapMessageEndpoints();
api.MapJobsEndpoints();
api.MapSubscriptionsEndpoints();

return app;
}
Expand Down
2 changes: 1 addition & 1 deletion backend/ResQueue/WebSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static void Main(string[] args)
app.MapGet("/publish",
async (IPublishEndpoint endpoint) => { await endpoint.Publish(new YourMessage(Guid.NewGuid())); });

app.MapGet("/schedule",
app.MapGet("/start-job",
async (IPublishEndpoint endpoint) =>
{
var jobId = await endpoint.AddOrUpdateRecurringJob(nameof(AwesomeConsumer), new AwesomeRequest(),
Expand Down
2 changes: 1 addition & 1 deletion backend/ResQueue/WebSample/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"Microsoft.AspNetCore": "Warning"
}
},
"Postgres": "Host=localhost;Database=sandbox100;Username=postgres;Password=postgres;",
"Postgres": "Host=localhost;Database=sandbox105;Username=postgres;Password=postgres;",
"SQL": "Server=localhost,1433;Database=sandbox100;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True",
"AllowedHosts": "*"
}
1 change: 1 addition & 0 deletions frontend/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare module 'vue' {
Column: typeof import('primevue/column')['default']
DataTable: typeof import('primevue/datatable')['default']
InputText: typeof import('primevue/inputtext')['default']
Listbox: typeof import('primevue/listbox')['default']
Menubar: typeof import('primevue/menubar')['default']
Popover: typeof import('primevue/popover')['default']
RouterLink: typeof import('vue-router')['RouterLink']
Expand Down
Loading
Loading