Workflow application.PersistableIdle event not firing - workflow-foundation-4

Hi I am new to Windows Workflow. This may be very easy, but I am stuck on this from long.
I have a state machine workflow, in which i have a workflow host class.
Persistence is not working in this code. While debugging pointer never goes to application.persistableIdle event.
I use custom input argument, for which I have set as Serializable.
below is my code of the host class:
static InstanceStore instanceStore;
static AutoResetEvent instanceUnloaded = new AutoResetEvent(false);
static Activity activity = new Activity1();
static Guid id = new Guid();
static int intContractHeaderKey;
static Contract contract = new Contract();
public ContractActivityHost(Guid wfid, Int32 contractHeaderID)
{
SetupInstanceStore();
StartAndUnloadInstance(contractHeaderID);
if (intContractHeaderKey > 0)
{
LoadAndCompleteInstance(id, intContractHeaderKey);
}
}
static void StartAndUnloadInstance(Int32 contractHeaderID)
{
contract = new Contract();
//var objContract = new object();
var input = new Dictionary<string, object>
{
{"TheContract", contract}
};
input.Add("ContractHeaderKey", contractHeaderID);
WorkflowApplication application = new WorkflowApplication(activity, input);
application.InstanceStore = instanceStore;
//returning IdleAction.Unload instructs the WorkflowApplication to persists application state and remove it from memory
application.PersistableIdle = (e) =>
{
return PersistableIdleAction.Unload;
};
application.Unloaded = (e) =>
{
instanceUnloaded.Set();
};
//application.Idle = (e) =>
// {
// //application.Unload();
// instanceUnloaded.Set();
// };
//This call is not required
//Calling persist here captures the application durably before it has been started
application.Persist();
id = application.Id;
application.Run();
instanceUnloaded.WaitOne();
//application.Unload();
//contract = (Contract)objContract;
intContractHeaderKey = contract.ContractID;
}
static void LoadAndCompleteInstance(Guid wfid, Int32 contractHeaderID)
{
//string input = Console.ReadLine();
while (!contract.ContractWFPause)
{
contract.FireContract(contract.ContractID);
WorkflowApplication application = new WorkflowApplication(activity);
application.InstanceStore = instanceStore;
application.Completed = (workflowApplicationCompletedEventArgs) =>
{
//Console.WriteLine("\nWorkflowApplication has Completed in the {0} state.", workflowApplicationCompletedEventArgs.CompletionState);
strWFStatus = "Completed";
};
application.Unloaded = (workflowApplicationEventArgs) =>
{
//Console.WriteLine("WorkflowApplication has Unloaded\n");
strWFStatus = "Unloaded";
instanceUnloaded.Set();
};
application.Load(wfid);
instanceUnloaded.WaitOne();
}
}
private static void SetupInstanceStore()
{
instanceStore =
new SqlWorkflowInstanceStore(#"Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;");
InstanceHandle handle = instanceStore.CreateInstanceHandle();
InstanceView view = instanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
handle.Free();
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
I have been trying to resolve this from long time, but not sure where I am missing anything. I have gone through couple of sample applications and changed my code to match the flow and logic, but still it does not work.
After application.persist, record is inserted in [System.Activities.DurableInstancing].[InstancesTable] view.
But debug pointer does not move beyond instanceUnloaded.WaitOne();
it actually goes to idle state. if I uncomment application.idle event, it goes in that event code.
Any help to resolve this would be great.
Thanks.

Please check If you have added the below details
instanceStore = new SqlWorkflowInstanceStore(ConfigurationManager.ConnectionStrings["WFPersistenceDb"].ConnectionString);
StateMachineStateTracker.Promote(this.instanceStore);

Related

Disable Asp.Net Core website during cache operation

I have some very heavy calculations for some statistics on my website that I want to update every 8 hours. I'm using a HostedService to update the cache every 8 hours. To disable the website, I create the app_offline.htm file at the root of the website.
This is a simplified version of the code:
public class CacheUpdaterHostedService : IHostedService
{
private readonly IServiceScopeFactory _scopeFactory;
private Timer _timer;
public CacheUpdaterHostedService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using var scope = _scopeFactory.CreateScope();
var contentRoot = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>().ContentRootPath;
var commissionService = scope.ServiceProvider.GetRequiredService<CommissionService>();
await commissionService.UpdateCacheAsync();
var interval = TimeSpan.FromHours(8);
var nextRunTime = GetNextRunTime(interval);
var firstInterval = nextRunTime.Subtract(DateTime.Now);
void action()
{
var t1 = Task.Delay(firstInterval, cancellationToken);
t1.Wait(cancellationToken);
_timer = new Timer(
async o =>
{
await FileHelper.CreateAppOfflineAsync(contentRoot);
using var scope = _scopeFactory.CreateScope();
var commissionService = scope.ServiceProvider.GetRequiredService<CommissionService>();
await commissionService.UpdateCacheAsync();
FileHelper.DeleteAppOffline(contentRoot);
},
null,
TimeSpan.Zero,
interval
);
}
Task.Run(action);
}
private static DateTime GetNextRunTime(TimeSpan interval)
{
var now = DateTime.Now;
var nextRunTime = DateTime.Today;
while(nextRunTime < now)
{
nextRunTime = nextRunTime.Add(interval);
}
return nextRunTime;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
Unfortunately sometimes for some reason, this fails and I have to manually delete the app_offline.htm and restart the website again to get it to work. Is there a more robust approach to taking the website offline while there are some services running?

Set a job to failed using Hangfire with ASP.NET?

I have an ASP.NET app which sends emails whenever the user signs up in the web site. I'm using hangfire in order to manage the jobs and postal in order to send emails.
It all works great, but here's the thing:
I want the superuser to change how many times the APP can send the email before deleting the job.
Here's my code
public static void WelcomeUser(DBContexts.Notifications not)
{
try{
var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(#"~/Views/Emails"));
var engines = new ViewEngineCollection();
engines.Add(new FileSystemRazorViewEngine(viewsPath));
Postal.EmailService service = new Postal.EmailService(engines);
WelcomeUserMail welcomeUserMail = new WelcomeUserMail();
welcomeUserMail.To = not.ReceiverEmail;
welcomeUserMail.UserEmail = not.ReceiverEmail;
welcomeUserMail.From = BaseNotification.GetEmailFrom();
service.Send(welcomeUserMail);
}
catch(Exception e)
{
DBContexts.DBModel dbModel = new DBModel();
DBContexts.Notifications notificacionBD = dbModel.Notifications.Find(not.NotificationID);
notificacionBD.Status = false;
notificacionBD.Timestamp = DateTime.Now;
notificacionBD.Error = e.Message;
int numberOfRetriesAllowed = ParameterHelper.getNumberOfRetriesAllowed();
if (notificacionBD.Retries > numberOfRetriesAllowed)
{
//In this case Hangfire won't put this job in the failed section but rather in the processed section.
dbModel.SaveChanges();
}
else
{
notificacionBD.Retries++;
dbModel.SaveChanges();
throw new Exception(e.Message);
}
}
}
Why not just add attributes to handle it automatically?
[AutomaticRetry(Attempts = 10, LogEvents = true, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
public void MyTask(){
//doing stuff
}
Or you could just make your own attribute that mimics the AutommaticRetryAttribute class but you handle it how you want?
https://github.com/HangfireIO/Hangfire/blob/a5761072f18ff4caa80910cda4652970cf52e693/src/Hangfire.Core/AutomaticRetryAttribute.cs

Threading for methods on button click

I am calling few methods on a button click.
functionA()
functionB()
functionC()
All three functions are independent from each other and they take long time to execute. I checked and found that by threading I can run all three together which will save the execution time.
As I am new to threading concept, could anyone please guide me the simplest way I can do threading in scenario or other way which will be useful in this scenario.
EDIT
One more problem in the same function:
I am binding 5 gridviews after the three functions execution. Like this
gv1.DataSource = GetData("Mill");
gv1.DataBind();
gv2.DataSource = GetData("Factory");
gv2.DataBind();
gv3.DataSource = GetData("Garage");
gv3.DataBind();
gv4.DataSource = GetData("Master");
gv4.DataBind();
They all are using the same method for getting the result and they are also taking time to load. Is there any way I can run them parallel too? I afraid, because they are using same method to get the data. Is it possible to do threading for them. How ?
I am not sure how Parallel.Invoke() decides what to execute in parallel, but if you want an assurance that they will execute in parallel, use threads:
var t1 = new Thread(MySlowFunction);
t1.IsBackground = true;
t1.Start();
var t2 = new Thread(MySlowFunction);
t2.IsBackground = true;
t2.Start();
# To resync after completion:
t1.Join();
t2.Join();
Or even better, use the ThreadPool:
ThreadPool.QueueUserWorkItem(MyWork);
Remember to handle your thread exceptions.
The simplest answer is to use MSDN: Parallel.Invoke().
You should also consider: Asynchronous Pages.
Try using System.Threading.Tasks namespace
Something like
var task1 = Task.Factory.StartNew(() => DoA());
var task2 = Task.Factory.StartNew(() => DoB());
var task3 = Task.Factory.StartNew(() => DoC());
Task.WaitAll(task1, task2, task3);
http://www.codethinked.com/net-40-and-systemthreadingtasks
Here's an example which will execute the 4 tasks in parallel:
public partial class _Default : System.Web.UI.Page
{
public class MyViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void BtnBindClick(object sender, EventArgs e)
{
// we define the input for the tasks: each element consists
// of the grid we are willing to bind the results at the end and
// some optional parameter we want to pass to the GetData function
var inputs = new[]
{
new { Grid = gv1, Input = "Mill" },
new { Grid = gv2, Input = "Factory" },
new { Grid = gv3, Input = "Garage" },
new { Grid = gv4, Input = "Master" },
};
// define the tasks we want to execute in parallel
var tasks = inputs
.Select(x => Task.Factory.StartNew(
() => new { Grid = x.Grid, Output = GetData(x.Input) })
)
.ToArray();
// define a task which will be executed once all tasks have finished
var finalTask = Task.Factory.ContinueWhenAll(tasks, x => x);
// wait for the final task
finalTask.Wait();
// consume the results
foreach (var item in finalTask.Result)
{
if (item.Exception == null)
{
// if no exception was thrown for this task we could bind the results
item.Result.Grid.DataSource = item.Result.Output;
item.Result.Grid.DataBind();
}
}
}
private MyViewModel[] GetData(string input)
{
// Simulate slowness
Thread.Sleep(1000);
return Enumerable.Range(1, 5).Select(x => new MyViewModel
{
Id = x,
Name = input
}).ToArray();
}
}

Moq Event Aggregator Is it possible

Wondering if its possible to Moq the Prism EventAggregator
Let's take the EventAggregator Quickstart they have
[TestMethod]
public void PresenterPublishesFundAddedOnViewAddClick()
{
var view = new MockAddFundView();
var EventAggregator = new MockEventAggregator();
var mockFundAddedEvent = new MockFundAddedEvent();
EventAggregator.AddMapping<FundAddedEvent>(mockFundAddedEvent);
var presenter = new AddFundPresenter(EventAggregator);
presenter.View = view;
view.Customer = "99";
view.Fund = "TestFund";
view.PublishAddClick();
Assert.IsTrue(mockFundAddedEvent.PublishCalled);
Assert.AreEqual("99", mockFundAddedEvent.PublishArgumentPayload.CustomerId);
}
I have tried to convert the above using moq but I get problems
they have MockEventAggregator.How can I do that using Moq?
public class MockEventAggregator : IEventAggregator
{
Dictionary<Type, object> events = new Dictionary<Type, object>();
public TEventType GetEvent<TEventType>() where TEventType : EventBase
{
return (TEventType)events[typeof(TEventType)];
}
public void AddMapping<TEventType>(TEventType mockEvent)
{
events.Add(typeof(TEventType), mockEvent);
}
}
Has anybody used MOQ and the EventAggregator are there any examples out there?
Thanks a lot
EDIT
Following GrameF Answer I have added my code that still does not work.Can you help
[TestMethod]
public void PresenterPublishesFundAddedOnViewAddClick2()
{
//Arrange
var view = new Mock<IAddFundView>();
var fakeEventAggregator = new Mock<IEventAggregator>();
var fakeMyEvent = new Mock<FundAddedEvent>();
fakeEventAggregator.Setup(x => x.GetEvent<FundAddedEvent>()).Returns(fakeMyEvent.Object);
var presenter = new AddFundPresenter(fakeEventAggregator.Object) {View = view.Object};
fakeMyEvent.Verify(x => x.Publish(It.IsAny<FundOrder>())); **//CRASHES** HERE
//view.PublishAddClick();
//view.Customer = "99";
//view.Fund = "TestFund";
//view.PublishAddClick();
////Assert
//Assert.IsTrue(mockFundAddedEvent.PublishCalled);
//Assert.AreEqual("99", mockFundAddedEvent.PublishArgumentPayload.CustomerId);
//Assert.AreEqual("TestFund", mockFundAddedEvent.PublishArgumentPayload.TickerSymbol);
}
Yes, it's possible, you just need to set it up to return a mock event on which you can verify that Publish or Subscribe was called:
var fakeEventAggregator = new Mock<IEventAggregator>();
var fakeMyEvent = new Mock<MyEvent>();
fakeEventAggregator.
Setup(x => x.GetEvent<MyEvent>()).
Returns(fakeMyEvent.Object);
var test = new Foo(fakeEventAggregator.Object);
test.PublishAnEvent();
fakeMyEvent.Verify(x => x.Publish(It.IsAny<MyEventArgs>()));

Can I get a series of good results and a thrown exception from Moq

I am mocking a wrapper to an MSMQ. The wrapper simply allows an object instance to be created that directly calls static methods of the MessageQueue class.
I want to test reading the queue to exhaustion. To do this I would like the mocked wrapper to return some good results and throw an exception on the fourth call to the same method. The method accepts no parameters and returns a standard message object.
Can I set up this series of expectations on the method in Moq?
Yup, this is possible if you don't mind jumping through a few minor hoops. I've done this for one of my projects before. Alright here is the basic technique. I just tested it out in Visual Studio 2008, and this works:
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<MyCustomException>();
});
A few notes:
You don't have to return mocked messages, but it's useful if you want to verify expectations on each message as well to see if certain methods were called or properties were set.
The queue idea is not my own, just a tip I got from a blog post.
The reason why I am throwing an exception of MyCustomException is because the Queue class automatically throws a InvalidOperationException. I wanted to make sure that the mocked MsmqWrapper object throws an exception because of Moq and not because of the queue running out of items.
Here's the complete code that works. Keep in mind that this code is ugly in some places, but I just wanted to show you how this could be tested:
public interface IMsmqWrapper
{
IMessage GetMessage();
}
public class MsmqWrapper : IMsmqWrapper
{
public IMessage GetMessage()
{
throw new NotImplementedException();
}
}
public class Processor
{
private IMsmqWrapper _wrapper;
public int MessagesProcessed { get; set; }
public bool ExceptionThrown { get; set; }
public Processor(IMsmqWrapper msmqWrapper)
{
_wrapper = msmqWrapper;
}
public virtual void ProcessMessages()
{
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
try
{
_wrapper.GetMessage();
}
catch (MyCustomException)
{
ExceptionThrown = true;
}
}
}
[Test]
public void TestMessageQueueGetsExhausted()
{
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<InvalidProgramException>();
});
var processor = new Processor(mockMsmqWrapper.Object);
processor.ProcessMessages();
Assert.That(processor.MessagesProcessed, Is.EqualTo(3));
Assert.That(processor.ExceptionThrown, Is.EqualTo(true));
}

Resources