Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1195 - Add Quartz.NET Tables to database migration + fix connect… #1196

Merged
merged 1 commit into from
Sep 10, 2022
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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) CGI France. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable disable

namespace AzureIoTHub.Portal.Infrastructure.Migrations
{
using Microsoft.EntityFrameworkCore.Migrations;

public partial class AddQuartzNETtables : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.Sql("DROP TABLE IF EXISTS qrtz_fired_triggers;\r\nDROP TABLE IF EXISTS qrtz_paused_trigger_grps;\r\nDROP TABLE IF EXISTS qrtz_scheduler_state;\r\nDROP TABLE IF EXISTS qrtz_locks;\r\nDROP TABLE IF EXISTS qrtz_simprop_triggers;\r\nDROP TABLE IF EXISTS qrtz_simple_triggers;\r\nDROP TABLE IF EXISTS qrtz_cron_triggers;\r\nDROP TABLE IF EXISTS qrtz_blob_triggers;\r\nDROP TABLE IF EXISTS qrtz_triggers;\r\nDROP TABLE IF EXISTS qrtz_job_details;\r\nDROP TABLE IF EXISTS qrtz_calendars;\r\n\r\n\r\nCREATE TABLE qrtz_job_details\r\n (\r\n sched_name TEXT NOT NULL,\r\n\tjob_name TEXT NOT NULL,\r\n job_group TEXT NOT NULL,\r\n description TEXT NULL,\r\n job_class_name TEXT NOT NULL, \r\n is_durable BOOL NOT NULL,\r\n is_nonconcurrent BOOL NOT NULL,\r\n is_update_data BOOL NOT NULL,\r\n\trequests_recovery BOOL NOT NULL,\r\n job_data BYTEA NULL,\r\n PRIMARY KEY (sched_name,job_name,job_group)\r\n);\r\n\r\nCREATE TABLE qrtz_triggers\r\n (\r\n sched_name TEXT NOT NULL,\r\n\ttrigger_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL,\r\n job_name TEXT NOT NULL, \r\n job_group TEXT NOT NULL,\r\n description TEXT NULL,\r\n next_fire_time BIGINT NULL,\r\n prev_fire_time BIGINT NULL,\r\n priority INTEGER NULL,\r\n trigger_state TEXT NOT NULL,\r\n trigger_type TEXT NOT NULL,\r\n start_time BIGINT NOT NULL,\r\n end_time BIGINT NULL,\r\n calendar_name TEXT NULL,\r\n misfire_instr SMALLINT NULL,\r\n job_data BYTEA NULL,\r\n PRIMARY KEY (sched_name,trigger_name,trigger_group),\r\n FOREIGN KEY (sched_name,job_name,job_group) \r\n\t\tREFERENCES qrtz_job_details(sched_name,job_name,job_group) \r\n);\r\n\r\nCREATE TABLE qrtz_simple_triggers\r\n (\r\n sched_name TEXT NOT NULL,\r\n\ttrigger_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL,\r\n repeat_count BIGINT NOT NULL,\r\n repeat_interval BIGINT NOT NULL,\r\n times_triggered BIGINT NOT NULL,\r\n PRIMARY KEY (sched_name,trigger_name,trigger_group),\r\n FOREIGN KEY (sched_name,trigger_name,trigger_group) \r\n\t\tREFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE\r\n);\r\n\r\nCREATE TABLE QRTZ_SIMPROP_TRIGGERS \r\n (\r\n sched_name TEXT NOT NULL,\r\n trigger_name TEXT NOT NULL ,\r\n trigger_group TEXT NOT NULL ,\r\n str_prop_1 TEXT NULL,\r\n str_prop_2 TEXT NULL,\r\n str_prop_3 TEXT NULL,\r\n int_prop_1 INTEGER NULL,\r\n int_prop_2 INTEGER NULL,\r\n long_prop_1 BIGINT NULL,\r\n long_prop_2 BIGINT NULL,\r\n dec_prop_1 NUMERIC NULL,\r\n dec_prop_2 NUMERIC NULL,\r\n bool_prop_1 BOOL NULL,\r\n bool_prop_2 BOOL NULL,\r\n\ttime_zone_id TEXT NULL,\r\n\tPRIMARY KEY (sched_name,trigger_name,trigger_group),\r\n FOREIGN KEY (sched_name,trigger_name,trigger_group) \r\n\t\tREFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE\r\n);\r\n\r\nCREATE TABLE qrtz_cron_triggers\r\n (\r\n sched_name TEXT NOT NULL,\r\n trigger_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL,\r\n cron_expression TEXT NOT NULL,\r\n time_zone_id TEXT,\r\n PRIMARY KEY (sched_name,trigger_name,trigger_group),\r\n FOREIGN KEY (sched_name,trigger_name,trigger_group) \r\n\t\tREFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE\r\n);\r\n\r\nCREATE TABLE qrtz_blob_triggers\r\n (\r\n sched_name TEXT NOT NULL,\r\n trigger_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL,\r\n blob_data BYTEA NULL,\r\n PRIMARY KEY (sched_name,trigger_name,trigger_group),\r\n FOREIGN KEY (sched_name,trigger_name,trigger_group) \r\n\t\tREFERENCES qrtz_triggers(sched_name,trigger_name,trigger_group) ON DELETE CASCADE\r\n);\r\n\r\nCREATE TABLE qrtz_calendars\r\n (\r\n sched_name TEXT NOT NULL,\r\n calendar_name TEXT NOT NULL, \r\n calendar BYTEA NOT NULL,\r\n PRIMARY KEY (sched_name,calendar_name)\r\n);\r\n\r\nCREATE TABLE qrtz_paused_trigger_grps\r\n (\r\n sched_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL, \r\n PRIMARY KEY (sched_name,trigger_group)\r\n);\r\n\r\nCREATE TABLE qrtz_fired_triggers \r\n (\r\n sched_name TEXT NOT NULL,\r\n entry_id TEXT NOT NULL,\r\n trigger_name TEXT NOT NULL,\r\n trigger_group TEXT NOT NULL,\r\n instance_name TEXT NOT NULL,\r\n fired_time BIGINT NOT NULL,\r\n\tsched_time BIGINT NOT NULL,\r\n priority INTEGER NOT NULL,\r\n state TEXT NOT NULL,\r\n job_name TEXT NULL,\r\n job_group TEXT NULL,\r\n is_nonconcurrent BOOL NOT NULL,\r\n requests_recovery BOOL NULL,\r\n PRIMARY KEY (sched_name,entry_id)\r\n);\r\n\r\nCREATE TABLE qrtz_scheduler_state \r\n (\r\n sched_name TEXT NOT NULL,\r\n instance_name TEXT NOT NULL,\r\n last_checkin_time BIGINT NOT NULL,\r\n checkin_interval BIGINT NOT NULL,\r\n PRIMARY KEY (sched_name,instance_name)\r\n);\r\n\r\nCREATE TABLE qrtz_locks\r\n (\r\n sched_name TEXT NOT NULL,\r\n lock_name TEXT NOT NULL, \r\n PRIMARY KEY (sched_name,lock_name)\r\n);\r\n\r\ncreate index idx_qrtz_j_req_recovery on qrtz_job_details(requests_recovery);\r\ncreate index idx_qrtz_t_next_fire_time on qrtz_triggers(next_fire_time);\r\ncreate index idx_qrtz_t_state on qrtz_triggers(trigger_state);\r\ncreate index idx_qrtz_t_nft_st on qrtz_triggers(next_fire_time,trigger_state);\r\ncreate index idx_qrtz_ft_trig_name on qrtz_fired_triggers(trigger_name);\r\ncreate index idx_qrtz_ft_trig_group on qrtz_fired_triggers(trigger_group);\r\ncreate index idx_qrtz_ft_trig_nm_gp on qrtz_fired_triggers(sched_name,trigger_name,trigger_group);\r\ncreate index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(instance_name);\r\ncreate index idx_qrtz_ft_job_name on qrtz_fired_triggers(job_name);\r\ncreate index idx_qrtz_ft_job_group on qrtz_fired_triggers(job_group);\r\ncreate index idx_qrtz_ft_job_req_recovery on qrtz_fired_triggers(requests_recovery);\r\n");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.Sql("DROP TABLE IF EXISTS qrtz_fired_triggers;\r\nDROP TABLE IF EXISTS qrtz_paused_trigger_grps;\r\nDROP TABLE IF EXISTS qrtz_scheduler_state;\r\nDROP TABLE IF EXISTS qrtz_locks;\r\nDROP TABLE IF EXISTS qrtz_simprop_triggers;\r\nDROP TABLE IF EXISTS qrtz_simple_triggers;\r\nDROP TABLE IF EXISTS qrtz_cron_triggers;\r\nDROP TABLE IF EXISTS qrtz_blob_triggers;\r\nDROP TABLE IF EXISTS qrtz_triggers;\r\nDROP TABLE IF EXISTS qrtz_job_details;\r\nDROP TABLE IF EXISTS qrtz_calendars;\r\n");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// <auto-generated />
// <auto-generated />
using AzureIoTHub.Portal.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#nullable disable

Expand Down
21 changes: 10 additions & 11 deletions src/AzureIoTHub.Portal/Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,20 @@ Specify the authorization token got from your IDP as a header.
_ = services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionJobFactory();
q.InterruptJobsOnShutdownWithWait = true;

q.UsePersistentStore(opts =>
{
// JSON is recommended persistent format to store data in database for greenfield projects.
// You should also strongly consider setting useProperties to true to restrict key - values to be strings.
opts.UseJsonSerializer();
opts.UseClustering();
opts.UseProperties = true;

opts.UsePostgres(configuration.StorageAccountConnectionString);
opts.UsePostgres(c =>
{
c.ConnectionString = configuration.PostgreSQLConnectionString;
});
});
});

Expand Down Expand Up @@ -405,7 +411,7 @@ public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
await deviceModelImageManager?.InitializeDefaultImageBlob()!;
await deviceModelImageManager?.SyncImagesCacheControl()!;

await EnsureDatabaseCreatedAndUpToDate(app, env)!;
await EnsureDatabaseCreatedAndUpToDate(app)!;
}

private static void UseApiExceptionMiddleware(IApplicationBuilder app)
Expand All @@ -429,19 +435,12 @@ private Task HandleApiFallback(HttpContext context)
return Task.CompletedTask;
}

private static async Task EnsureDatabaseCreatedAndUpToDate(IApplicationBuilder app, IWebHostEnvironment env)
private static async Task EnsureDatabaseCreatedAndUpToDate(IApplicationBuilder app)
{
using var scope = app.ApplicationServices.CreateScope();

using var context = scope.ServiceProvider.GetRequiredService<PortalDbContext>();

if (env.IsDevelopment())
{
_ = await context.Database.EnsureDeletedAsync();
}

// Create the database if not exists and migrate it using the database bigration scripts.
_ = await context.Database.EnsureCreatedAsync();
await context.Database.MigrateAsync();
}
}
}