I have this simple self hosted "Hello World" app which I doesn't understand how it works 100 %.
namespace HelloOwin
{
using System;
using Microsoft.Owin.Hosting;
using Owin;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;
class Program
{
static void Main(string[] args)
{
using(WebApp.Start<Startup>(url: "http://localhost:9765/"))
{
Console.ReadLine();
}
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Run(context =>
{
var task = context.Response.WriteAsync("Hello world!");
return task;
});
}
}
}
For each request I'm doing to this application the Func defined in app.Run is run twice, why so?
Preinitialization calls means just some code that you want to be executed before you call configureapp in the startup. you can do some operation that requires this or some logging really depends on your requirements.
Related
I would also like that on multiple runs the data is not stacked multiple times.
I have done this once with spring boot's CommandLineRunner:
#SpringBootApplication
public class HamstergotchiApplication {
public static void main(String[] args) {
SpringApplication.run(HamstergotchiApplication.class, args);
}
/**
* Add challenges on startup if there are no challenges in the database.
* This will be run at startup.
*/
#Bean
public CommandLineRunner initializeDB(ChallengeRepository challengeRepository){
return (args)->{
// Add default challenges if the DB is empty
if(challengeRepository.count() == 0) {
challengeRepository.save(new Challenge(0, ChallengeType.GEEN_ALCOHOL, false));
challengeRepository.save(new Challenge(0, ChallengeType.MINDER_FRISDRANK_MET_SUIKER, true));
challengeRepository.save(new Challenge(0, ChallengeType.GROENTE_EN_FRUIT_20_PROCENT, false));
challengeRepository.save(new Challenge(0, ChallengeType.GEEN_VLEES, true);
}
};
}
}
You might want a separate script/command to initialize the database.
If you don't want that, well, just something like
async function initializeDatabase() {
if(databaseContainsEntries()) return;
addEntry(...);
addEntry(...);
addEntry(...);
addEntry(...);
}
async function boot() {
await initializeDatabase();
app.listen(...);
}
boot();
instead of a vanilla
app.listen(...);
I could just write a long-running CLI app and run it, but I'm assuming it wouldn't comply to all the expectations one would have of a standards-compliant linux daemon (responding to SIGTERM, Started by System V init process, Ignore terminal I/O signals, etc.)
Most ecosystems have some best-practice way of doing this, for example, in python, you can use https://pypi.python.org/pypi/python-daemon/
Is there some documentation about how to do this with .Net Core?
I toyed with an idea similar to how .net core web host waits for shutdown in console applications. I was reviewing it on GitHub and was able to extract the gist of how they performed the Run
https://github.com/aspnet/Hosting/blob/15008b0b7fcb54235a9de3ab844c066aaf42ea44/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs#L86
public static class ConsoleHost {
/// <summary>
/// Block the calling thread until shutdown is triggered via Ctrl+C or SIGTERM.
/// </summary>
public static void WaitForShutdown() {
WaitForShutdownAsync().GetAwaiter().GetResult();
}
/// <summary>
/// Runs an application and block the calling thread until host shutdown.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
public static void Wait() {
WaitAsync().GetAwaiter().GetResult();
}
/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IConsoleHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task WaitAsync(CancellationToken token = default(CancellationToken)) {
//Wait for the token shutdown if it can be cancelled
if (token.CanBeCanceled) {
await WaitAsync(token, shutdownMessage: null);
return;
}
//If token cannot be cancelled, attach Ctrl+C and SIGTERN shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource()) {
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
await WaitAsync(cts.Token, "Application running. Press Ctrl+C to shut down.");
done.Set();
}
}
/// <summary>
/// Returns a Task that completes when shutdown is triggered via the given token, Ctrl+C or SIGTERM.
/// </summary>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task WaitForShutdownAsync(CancellationToken token = default (CancellationToken)) {
var done = new ManualResetEventSlim(false);
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token)) {
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: string.Empty);
await WaitForTokenShutdownAsync(cts.Token);
done.Set();
}
}
private static async Task WaitAsync(CancellationToken token, string shutdownMessage) {
if (!string.IsNullOrEmpty(shutdownMessage)) {
Console.WriteLine(shutdownMessage);
}
await WaitForTokenShutdownAsync(token);
}
private static void AttachCtrlcSigtermShutdown(CancellationTokenSource cts, ManualResetEventSlim resetEvent, string shutdownMessage) {
Action ShutDown = () => {
if (!cts.IsCancellationRequested) {
if (!string.IsNullOrWhiteSpace(shutdownMessage)) {
Console.WriteLine(shutdownMessage);
}
try {
cts.Cancel();
} catch (ObjectDisposedException) { }
}
//Wait on the given reset event
resetEvent.Wait();
};
AppDomain.CurrentDomain.ProcessExit += delegate { ShutDown(); };
Console.CancelKeyPress += (sender, eventArgs) => {
ShutDown();
//Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}
private static async Task WaitForTokenShutdownAsync(CancellationToken token) {
var waitForStop = new TaskCompletionSource<object>();
token.Register(obj => {
var tcs = (TaskCompletionSource<object>)obj;
tcs.TrySetResult(null);
}, waitForStop);
await waitForStop.Task;
}
}
I tried adapting something like a IConsoleHost but quickly realized I was over-engineering it. Extracted the main parts into something like await ConsoleUtil.WaitForShutdownAsync(); that operated like Console.ReadLine
This then allowed the utility to be used like this
public class Program {
public static async Task Main(string[] args) {
//relevant code goes here
//...
//wait for application shutdown
await ConsoleUtil.WaitForShutdownAsync();
}
}
from there creating a systemd as in the following link should get you the rest of the way
Writing a Linux daemon in C#
The best I could come up with is based on the answer to two other questions: Killing gracefully a .NET Core daemon running on Linux and Is it possible to await an event instead of another async method?
using System;
using System.Runtime.Loader;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public class Program
{
private static TaskCompletionSource<object> taskToWait;
public static void Main(string[] args)
{
taskToWait = new TaskCompletionSource<object>();
AssemblyLoadContext.Default.Unloading += SigTermEventHandler;
Console.CancelKeyPress += new ConsoleCancelEventHandler(CancelHandler);
//eventSource.Subscribe(eventSink) or something...
taskToWait.Task.Wait();
AssemblyLoadContext.Default.Unloading -= SigTermEventHandler;
Console.CancelKeyPress -= new ConsoleCancelEventHandler(CancelHandler);
}
private static void SigTermEventHandler(AssemblyLoadContext obj)
{
System.Console.WriteLine("Unloading...");
taskToWait.TrySetResult(null);
}
private static void CancelHandler(object sender, ConsoleCancelEventArgs e)
{
System.Console.WriteLine("Exiting...");
taskToWait.TrySetResult(null);
}
}
}
Implementing Linux Daemon or service for windows quite easy with single codebase using Visual Studio 2019. Just create project using WorkerService template. In my case I have
Coraval library to schedule the tasks.
Program.cs class
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File(#"C:\temp\Workerservice\logfile.txt").CreateLogger();
IHost host = CreateHostBuilder(args).Build();
host.Services.UseScheduler(scheduler =>
{
scheduler
.Schedule<ReprocessInvocable>()
.EveryThirtySeconds();
});
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).UseSystemd() //.UseWindowsService()
.ConfigureServices(services =>
{
services.AddScheduler();
services.AddTransient<ReprocessInvocable>();
});
}
ReprocessInvocable.cs class
public class ReprocessInvocable : IInvocable
{
private readonly ILogger<ReprocessInvocable> _logger;
public ReprocessInvocable(ILogger<ReprocessInvocable> logger)
{
_logger = logger;
}
public async Task Invoke()
{
//your code goes here
_logger.LogInformation("Information - Worker running at: {time}", DateTimeOffset.Now);
_logger.LogWarning("Warning - Worker running at: {time}", DateTimeOffset.Now);
_logger.LogCritical("Critical - Worker running at: {time}", DateTimeOffset.Now);
Log.Information("Invoke has called at: {time}", DateTimeOffset.Now);
}
}
For linux daemon use UseSystemd and for windows service use UseWindowsService as per the above code.
If you're trying to find something more robust, I found an implementation on Github that looks promising: .NET Core Application blocks for message-based communication. It uses Host, HostBuilder, ApplicationServices, ApplicationEnvironment, etc classes to implement a messaging service.
It doesn't quite look ready for black box reuse, but it seems like it could be a good starting point.
var host = new HostBuilder()
.ConfigureServices(services =>
{
var settings = new RabbitMQSettings { ServerName = "192.168.80.129", UserName = "admin", Password = "Pass#word1" };
})
.Build();
Console.WriteLine("Starting...");
await host.StartAsync();
var messenger = host.Services.GetRequiredService<IRabbitMQMessenger>();
Console.WriteLine("Running. Type text and press ENTER to send a message.");
Console.CancelKeyPress += async (sender, e) =>
{
Console.WriteLine("Shutting down...");
await host.StopAsync(new CancellationTokenSource(3000).Token);
Environment.Exit(0);
};
...
Have you tried Thread.Sleep (Timeout.Infinite) ?
using System;
using System.IO;
using System.Threading;
namespace Daemon {
class Program {
static int Main(string[] args) {
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
Log.Critical("Windows is not supported!");
return 1;
}
Agent.Init();
Agent.Start();
if (Agent.Settings.DaemonMode || args.FirstOrDefault() == "daemon") {
Log.Info("Daemon started.");
Thread.Sleep(Timeout.Infinite);
}
Agent.Stop();
}
}
}
I'm not sure it is production grade, but for a quick and dirty console app this works well:
await Task.Delay(-1); //-1 indicates infinite timeout
I have this code in my project that I uploaded to Azure Web Job.
class Program {
static void Main(string[] args) {
var host = new JobHost();
host.RunAndBlock();
}
public static async Task AddSomethingAsync([QueueInput("myqueue1")] string _)
{
//....
}
public static async Task UpdateSomethingAsync([QueueInput("myqueue2")] string _)
{
//....
}
}
}
But it shows the first function "AddSomethingAsync" only in azure scm site (https://me.scm.azurewebsites.net/azurejobs/#/jobs/triggered/myjob/runs/201406170707442616)
Is it the known issue or Am I missing something?
Thanks!
Okie. I got it now. I need to go to Functions page to see it. The default shows only the first method.
I'm building mvc3 application that should serve about 1000-2000 concurrent users,
I implemented Castle Active Record and simple repository pattern, now i need to unit test all this that it won't crash on concurrency and in multi-thread environment like iis.
How should I do it?
I'm using nunit testing framework.
My Repository:
//interface
public interface IAbstractRepository<T> where T : class
{
void Create(T model);
void Update(T model);
void Delete(T model);
int Count();
T FindById(object id);
T FindOne(params ICriterion[] criteria);
IList<T> FindAll();
IList<T> FindAllByCriteria(params ICriterion[] criteria);
}
//concrete implementation
public class AbstractRepository<T> : IAbstractRepository<T> where T : class
{
void IAbstractRepository<T>.Create(T model)
{
ActiveRecordMediator<T>.Save(model);
}
void IAbstractRepository<T>.Update(T model)
{
ActiveRecordMediator<T>.Update(model);
}
void IAbstractRepository<T>.Delete(T model)
{
ActiveRecordMediator<T>.Delete(model);
}
int IAbstractRepository<T>.Count()
{
return ActiveRecordMediator<T>.Count();
}
T IAbstractRepository<T>.FindById(object id)
{
return ActiveRecordMediator<T>.FindByPrimaryKey(id);
}
T IAbstractRepository<T>.FindOne(params ICriterion[] criteria)
{
return ActiveRecordMediator<T>.FindOne(criteria);
}
IList<T> IAbstractRepository<T>.FindAll()
{
return ActiveRecordMediator<T>.FindAll();
}
IList<T> IAbstractRepository<T>.FindAllByCriteria(params ICriterion[] criteria)
{
return ActiveRecordMediator<T>.FindAll(criteria);
}
}
That's no longer a unit test what you are trying to do. It's a load test. There are some tools out there that allow you to record some scenario and then simulate concurrent access to your web application executing this scenario:
Visual Studio Load Tests
loadUI
Apache Bench
Apache JMeter
Pylot
Tsung
Siege
I'm trying to get windows workflows working, and I've become a little stumped.
I've gotten a single workflow working, but now I am trying to do something a little more complex: start a workflow, where each activity itself contains a workflow. (Picture something like the main program starts the activities "Input, logic, and output", and then each of those have additional activities like "prompt user, get input, etc.")
I've had it working fine, with the example from here (http://msdn.microsoft.com/en-us/magazine/gg535667.aspx), when I am not passing any parameters from the main program to the activites. My question is, how exactly does the 'Variables' and 'metadata.SetVariablesCollection' work in the NativeActivity, and how to I get the parameters to the low level activities?
This is what I am currently trying:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Collections.ObjectModel;
using System.Activities.Statements;
namespace Project1
{
internal class MainProgram
{
internal static void Main(string[] args)
{
try
{
var act = new SimpleSequence();
act.Activities.Add((Activity)(new WriteSomeText()));
act.Activities.Add((Activity)(new WriteSomeText()));
act.Activities.Add((Activity)(new WriteSomeText()));
act.Variables.Add(new Variable<string> ("stringArg", "TEXT"));
WorkflowInvoker.Invoke(act);
}
catch (Exception ex)
{
System.Console.WriteLine("EXCEPTION: {0}", ex);
}
}
public class WriteSomeText : CodeActivity
{
[RequiredArgument]
public InArgument<string> stringArg { get; set; }
protected override void Execute(CodeActivityContext context)
{
string output = context.GetValue(stringArg);
System.Console.WriteLine(output);
}
}
public class SimpleSequence : NativeActivity
{
Collection<Activity> activities;
Collection<Variable> variables;
Variable<int> current = new Variable<int> { Default = 0 };
public Collection<Activity> Activities
{
get
{
if (this.activities == null)
this.activities = new Collection<Activity>();
return this.activities;
}
set
{
this.activities = value;
}
}
public Collection<Variable> Variables
{
get
{
if (this.variables == null)
this.variables = new Collection<Variable>();
return this.variables;
}
set
{
this.variables = value;
}
}
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.SetChildrenCollection(this.activities);
metadata.SetVariablesCollection(this.variables);
metadata.AddImplementationVariable(this.current);
}
protected override void Execute(NativeActivityContext context)
{
if (this.Activities.Count > 0)
context.ScheduleActivity(this.Activities[0], onChildComplete);
}
void onChildComplete(NativeActivityContext context, ActivityInstance completed)
{
int currentExecutingActivity = this.current.Get(context);
int next = currentExecutingActivity + 1;
if (next < this.Activities.Count)
{
context.ScheduleActivity(this.Activities[next], this.onChildComplete);
this.current.Set(context, next);
}
}
}
}
}
This ends up throwing the following exception:
EXCEPTION: System.Activities.InvalidWorkflowException: The following errors were encountered while processing the workflow tree:
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
at System.Activities.Validation.ActivityValidationServices.ThrowIfViolationsExist(IList`1 validationErrors)
at System.Activities.Hosting.WorkflowInstance.ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager)
at System.Activities.Hosting.WorkflowInstance.RegisterExtensionManager(WorkflowInstanceExtensionManager extensionManager)
at System.Activities.WorkflowApplication.EnsureInitialized()
at System.Activities.WorkflowApplication.RunInstance(WorkflowApplication instance)
at System.Activities.WorkflowApplication.Invoke(Activity activity, IDictionary`2 inputs, WorkflowInstanceExtensionManager extensions, TimeSpan timeout)
at System.Activities.WorkflowInvoker.Invoke(Activity workflow, TimeSpan timeout, WorkflowInstanceExtensionManager extensions)
at System.Activities.WorkflowInvoker.Invoke(Activity workflow)
at Project1.MainProgram.Main(String[] args) in c:\users\user\documents\visual studio 2010\Projects\ModelingProject1\Project1\MainProgram.cs:line 25
I know, I only pass 1 parameter, but the exception still says that I am missing 3 parameters. I am missing something as to how to do this properly.
You're correctly declaring stringArg as an InArgument but you're not passing any value to it when calling it inside SimpleSequence.
You can pass something using the constructor, while constructing the all activity itself, like this:
public class WriteSomeText : CodeActivity
{
[RequiredArgument]
public InArgument<string> stringArg { get; set; }
public WriteSomeText(string stringArg)
{
this.stringArg = stringArg;
}
protected override void Execute(CodeActivityContext context
{
string output = context.GetValue(stringArg);
System.Console.WriteLine(output);
}
}
// Calling the activity like this:
internal static void Main(string[] args)
{
var act = new SimpleSequence()
{
Activities =
{
new WriteSomeText("hello"),
new WriteSomeText("world"),
new WriteSomeText("!")
}
};
WorkflowInvoker.Invoke(act);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Also notice that is a best practice to use the constructor to initialize collections:
public SimpleSequence()
{
activities = new Collection<Activity>();
variables = new Collection<Variable>();
}
This way is even more intuitive to initialize the activity:
var act = new SimpleSequence()
{
Activities =
{
new WriteSomeText("hello"),
new WriteSomeText("world"),
new WriteSomeText("!")
},
Variables =
{
new Variable<int>("myNewIntVar", 10),
// ....
}
};
EDIT:
There are a couple of other ways to approach the problem. This is your best friend while starting in the WF4 world.
Check WF\Basic\CustomActivities\Code-Bodied for a little push with this particular case.