Skip to content

Commit 4d33a96

Browse files
authored
Merge pull request #681 from ErikEJ/sqlproject-delay
fixes #638
2 parents dbefa30 + 9697f15 commit 4d33a96

File tree

3 files changed

+71
-13
lines changed

3 files changed

+71
-13
lines changed

examples/sql-database-projects/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.AppHost/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@
2121
builder.AddSqlProject<Projects.SdkProject>("existing-db")
2222
.WithReference(connection);
2323

24+
var delayedProject = builder.AddSqlProject<Projects.SdkProject>("sdk-project-delayed")
25+
.WithReference(database)
26+
.WithExplicitStart();
27+
2428
builder.Build().Run();

src/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects/SqlProjectBuilderExtensions.cs

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,35 +198,68 @@ internal static IResourceBuilder<TResource> InternalWithReference<TResource>(thi
198198
{
199199
builder.ApplicationBuilder.Eventing.Subscribe<ResourceReadyEvent>(target.Resource, async (resourceReady, ct) =>
200200
{
201-
await RunPublish(builder, target, targetDatabaseName, resourceReady.Services, ct);
201+
await PublishOrMark(builder, target, targetDatabaseName, resourceReady.Services, ct);
202202
});
203203
}
204-
else
204+
else
205205
{
206-
builder.ApplicationBuilder.Eventing.Subscribe<AfterResourcesCreatedEvent>(async (@event, ct) => {
207-
await RunPublish(builder, target, targetDatabaseName, @event.Services, ct);
206+
builder.ApplicationBuilder.Eventing.Subscribe<AfterResourcesCreatedEvent>(async (@event, ct) =>
207+
{
208+
await PublishOrMark(builder, target, targetDatabaseName, @event.Services, ct);
208209
});
209210
}
210211

211212
builder.WaitFor(target);
212213

213-
builder.WithCommand("redeploy", "Redeploy", async (context) =>
214-
{
215-
var service = context.ServiceProvider.GetRequiredService<SqlProjectPublishService>();
216-
await service.PublishSqlProject(builder.Resource, target.Resource, targetDatabaseName, context.CancellationToken);
217-
return new ExecuteCommandResult { Success = true };
218-
}, new CommandOptions()
214+
var commandOptions = new CommandOptions
219215
{
220-
Description = "Redeploys the SQL Server Database Project to the target database.",
221216
IconName = "ArrowReset",
222217
IconVariant = IconVariant.Filled,
223218
IsHighlighted = true,
224-
UpdateState = (context) => context.ResourceSnapshot?.State?.Text == KnownResourceStates.Finished ? ResourceCommandState.Enabled : ResourceCommandState.Disabled,
225-
});
219+
Description = "Deploy the SQL Server Database Project to the target database.",
220+
UpdateState = (context) =>
221+
{
222+
if (context.ResourceSnapshot?.State?.Text is string stateText && (stateText == KnownResourceStates.Finished || stateText == KnownResourceStates.NotStarted))
223+
{
224+
return ResourceCommandState.Enabled;
225+
}
226+
else
227+
{
228+
return ResourceCommandState.Disabled;
229+
}
230+
},
231+
};
232+
233+
builder.WithCommand("deploy", "Deploy", async (context) =>
234+
{
235+
var service = context.ServiceProvider.GetRequiredService<SqlProjectPublishService>();
236+
await service.PublishSqlProject(builder.Resource, target.Resource, targetDatabaseName, context.CancellationToken);
237+
return new ExecuteCommandResult { Success = true };
238+
}, commandOptions);
226239

227240
return builder;
228241
}
229242

243+
private static async Task PublishOrMark<TResource>(IResourceBuilder<TResource> builder, IResourceBuilder<IResourceWithConnectionString> target, string? targetDatabaseName, IServiceProvider services, CancellationToken ct) where TResource : IResourceWithDacpac
244+
{
245+
if (builder.Resource.HasAnnotationOfType<ExplicitStartupAnnotation>())
246+
{
247+
await MarkNotStarted(builder, services);
248+
}
249+
else
250+
{
251+
await RunPublish(builder, target, targetDatabaseName, services, ct);
252+
}
253+
}
254+
255+
private static async Task MarkNotStarted<TResource>(IResourceBuilder<TResource> builder, IServiceProvider serviceProvider)
256+
where TResource : IResourceWithDacpac
257+
{
258+
var resourceNotificationService = serviceProvider.GetRequiredService<ResourceNotificationService>();
259+
await resourceNotificationService.PublishUpdateAsync(builder.Resource,
260+
state => state with { State = new ResourceStateSnapshot(KnownResourceStates.NotStarted, KnownResourceStateStyles.Info) });
261+
}
262+
230263
private static async Task RunPublish<TResource>(IResourceBuilder<TResource> builder, IResourceBuilder<IResourceWithConnectionString> target, string? targetDatabaseName, IServiceProvider serviceProvider, CancellationToken ct)
231264
where TResource : IResourceWithDacpac
232265
{

tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/AddSqlProjectTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,25 @@ public void WithReference_AddsRequiredServices()
110110
Assert.Single(app.Services.GetServices<SqlProjectPublishService>());
111111
Assert.Single(app.Services.GetServices<IDacpacDeployer>());
112112
}
113+
114+
[Fact]
115+
public void AddSqlProject_WithExplicitStart()
116+
{
117+
// Arrange
118+
var appBuilder = DistributedApplication.CreateBuilder();
119+
var targetDatabase = appBuilder.AddSqlServer("sql").AddDatabase("test");
120+
appBuilder.AddSqlProject<TestProject>("MySqlProject")
121+
.WithReference(targetDatabase)
122+
.WithExplicitStart();
123+
124+
// Act
125+
using var app = appBuilder.Build();
126+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
127+
128+
// Assert
129+
var sqlProjectResource = Assert.Single(appModel.Resources.OfType<SqlProjectResource>());
130+
Assert.Equal("MySqlProject", sqlProjectResource.Name);
131+
132+
Assert.True(sqlProjectResource.HasAnnotationOfType<ExplicitStartupAnnotation>());
133+
}
113134
}

0 commit comments

Comments
 (0)