I have couple of tables in the DB, one to stores the list of Holidays(HolidayWeeks) in the year and other one to store the setting(Settings) like when an application should be running. Both the tables are like below in the Azure DB
I started to build the Timer Triggered AzureFunction to check everyday at 5 AM if today doesnot fall under the Holiday list as well Today (Day of the week ) is equal to the Order day in the Settings table like below
public static class StartorStopSMAppService
{
[FunctionName("StartorStopSMAppService")]
public static void Run([TimerTrigger("0 0 5 * * *")]TimerInfo myTimer, ILogger log)
{
int holidaychk = 0;
var str = Environment.GetEnvironmentVariable("SurplusMouseDBConnection");
using (SqlConnection conn = new SqlConnection(str))
{
try
{
conn.Open();
var settingscheck = "SELECT TOP 1 [EndTime],[StartTime],[OrderDay]"
"FROM[dbo].[Settings]"
"where SUBSTRING(DATENAME(weekday, getdate() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'), 0, 4) = OrderDay";
var holidaycheck = "SELECT Count(*) FROM[dbo].[HolidayWeeks] where FORMAT(getdate(), 'yyyy-MM-dd') = [HolidateDate]";
SqlCommand cmd1 = new SqlCommand(holidaycheck, conn);
holidaychk = (Int32)cmd1.ExecuteScalar();
if (holidaychk != 0)
{
SqlCommand command = new SqlCommand(settingscheck, conn);
using (SqlDataReader reader = command.ExecuteReader())
{
reader.Read();
if (reader.HasRows)
{
var starttime = reader["StartTime"].ToString();
var endtime = reader["EndTime"].ToString();
// Not sure how to call the start API at this starttime time
}}}}
catch (Exception ex)
{
log.LogInformation(ex.Message);
}
finally
{
if (conn.State != ConnectionState.Closed)
{
conn.Close();
} }}
When the both the conditions are satisfied I need to start the web service on the starttime give on the Settings table which I am storing in the var starttime = reader["StartTime"].ToString();
I understand that I can POST call the API https://docs.microsoft.com/en-us/rest/api/appservice/web-apps/start to start Web App in the App Service. But how can start the application based on starttime
variable. I am kind of stuck any help is greatly appreciated
CodePudding user response:
Once your code determines that it is not a holiday and you would like to start the web app at that particular time, you can post a scheduled message
to Azure Queue, see this. If you write a Azure Function Queue trigger, as and when it gets invoked, it can call the start
REST API for your WebApp.
CodePudding user response:
Its possible with Durable functions as well. You can implement this as below.
- Timer trigger function
public static class TimerFunction
{
[FunctionName("ScheduledStart")]
public static async Task RunScheduled([TimerTrigger("0 * * * * *")] TimerInfo timerInfo,[DurableClient] IDurableClient starter,ILogger log)
{
string functionName = "OrchestractionFunction";
string time = "26/10/2021 7:00AM";
var startTime = DateTime.Parse(time).ToUniversalTime();
string instanceId = await starter.StartNewAsync(functionName, Guid.NewGuid().ToString(), startTime);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
}
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
- Create a Durable function with delay
`
[FunctionName("OrchestractionFunction")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var startTime = context.GetInput<DateTime>();
Console.WriteLine(startTime);
await context.CreateTimer(startTime, CancellationToken.None);
await context.CallActivityAsync("ActivityFunction", "Jhon");
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
`
- Activity function invoking a Http request
[FunctionName("ActivityFunction")]
public static string SayHello([ActivityTrigger] string name, ILogger log){
log.LogInformation(name);
//HttpRequest here
}
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
you can extend the orchestration function to call multiple different APIs
CodePudding user response:
The other two answers are good, but using your current code, all you need to do is check if current date is greater than start time, then, perform the request. Here's a sample using Flurl to simplify the request:
public static class StartorStopSMAppService {
[FunctionName("StartorStopSMAppService")]
public static void Run([TimerTrigger("0 0 5 * * *")] TimerInfo myTimer, ILogger log) {
int holidaychk = 0;
var str = Environment.GetEnvironmentVariable("SurplusMouseDBConnection");
using(SqlConnection conn = new SqlConnection(str)) {
try {
conn.Open();
var settingscheck = "SELECT TOP 1 [EndTime],[StartTime],[OrderDay]"
"FROM[dbo].[Settings]"
"where SUBSTRING(DATENAME(weekday, getdate() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'), 0, 4) = OrderDay";
var holidaycheck = "SELECT Count(*) FROM[dbo].[HolidayWeeks] where FORMAT(getdate(), 'yyyy-MM-dd') = [HolidateDate]";
SqlCommand cmd1 = new SqlCommand(holidaycheck, conn);
holidaychk = (Int32) cmd1.ExecuteScalar();
if (holidaychk != 0) {
SqlCommand command = new SqlCommand(settingscheck, conn);
using(SqlDataReader reader = command.ExecuteReader()) {
reader.Read();
if (reader.HasRows) {
var starttime = reader["StartTime"].ToString();
var endtime = reader["EndTime"].ToString();
string subscriptionId = ""; // enter this value
string resourceGroupName = ""; // enter this value
string webAppName = ""; // enter this value
string url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{webAppName}/start?api-version=2021-02-01";
DateTime dStartTime;
DateTime.TryParse(starttime, out dStartTime);
if (DateTime.UtcNow >= dStartTime){
await url.PostAsync(); // requires Flurl.Http package
}
}
}
}
} catch (Exception ex) {
log.LogInformation(ex.Message);
} finally {
if (conn.State != ConnectionState.Closed) {
conn.Close();
}
}
}