Quartz.net Manually trigger job from Web API - quartz.net-3.0

I realize this has sort of been asked before but I want to get a clear confirmation.
I have a Windows Service running the Quartz.Net Scheduler. Jobs and Triggers have been created.
We will have an angular web client that will at times, need to fire jobs manually.
So in a Web API Controller, I have code like this:
var properties = new NameValueCollection
{
["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
["quartz.jobStore.useProperties"] = "true",
["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",
["quartz.jobStore.dataSource"] = "myDS",
["quartz.jobStore.tablePrefix"] = "QRTZ_",
["quartz.dataSource.NAME.provider"] = "SqlServer",
["quartz.dataSource.NAME.connectionString"] = "Server=localhost;Database=QuartzScheduler;Uid=blahuser;Pwd=blahpwd",
["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"
};
var sched = new StdSchedulerFactory(properties).GetScheduler().Result;
var jobKey = new JobKey("DailyJob1130EST", "DailyGroup");
var jobDataMap = new JobDataMap();
jobDataMap.Add("listIds", "33333");
sched.TriggerJob(jobKey, jobDataMap);
The Job Name and Group do exist in the database.
I was hoping that the call to TriggerJob would cause the Scheduler I have running in my windows service, to fire the job. But it doesn't. Nothing happens, not even an error.
BTW, I don't want to use remoting since it requires the full .NET Framework and the help docs say that it is considered unsafe.
If TriggerJob doesn't work, I guess to run a job manually I'd have to add a new trigger to the scheduler to run once, or something???

There may be other ways, but one way that I was able to successfully do it was:
var sched = await new StdSchedulerFactory(properties).GetScheduler();
var jobKey = new JobKey("DailyJob1130EST", "DailyGroup");
var jobDataMap = new JobDataMap();
jobDataMap.Add("listIds", rInt.ToString());
var trig = TriggerBuilder.Create()
.WithIdentity("RunNowTrigger")
.StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5)))
.WithDescription("Run Now Trigger")
.Build();
sched.TriggerJob(jobKey, jobDataMap);
Note: "properties" were my NameValueCollection config information, which I omitted from the sample code. It was nothing out of the ordinary. It just setup the jobStore, dataSource, serializer.type and threadPool.type settings.

Related

Dotmim.Sync is throwing exception when synchronizing existing SQLite with SQL Server databases

I get a Dotmim.Sync.SyncException when calling the agent.SynchronizeAsync(tables) function:
Exception: Seems you are trying another Setup tables that what is stored in your server scope database. Please make a migration or create a new scope
This is my code:
public static async Task SynchronizeAsync()
{
var serverProvider = new SqlSyncProvider(serverConnectionString);
// Second provider is using plain old Sql Server provider, relying on triggers and tracking tables to create the sync environment
var clientProvider = new SqliteSyncProvider(Path.Combine(FileSystem.AppDataDirectory, "treesDB.db3"));
// Tables involved in the sync process:
var tables = new string[] { "Trees" };
// Creating an agent that will handle all the process
var agent = new SyncAgent(clientProvider, serverProvider);
// Launch the sync process
var s1 = await agent.SynchronizeAsync(tables);
await agent.LocalOrchestrator.UpdateUntrackedRowsAsync();
var s2 = await agent.SynchronizeAsync();
}
I'm the author of Dotmim.Sync
Do not hesitate to to fill an issue on Github if you are still struggling.
Regarding your issue, I think you have made some tests with different tables.
You need to stick with a set of tables, because DMS needs to create different things (triggers / stored proc and so on)
If you want to test different setups, you need to define differents scopes.
You have a complete documentation on https://dotmimsync.readthedocs.io/

CefSharp Wpf , Session Cookie for multiple instances

I am very curious if there is a possibility in CEF Sharp , somehow to isolate each instance of browser from other instances.
I am creating 4 instances of browser. Logging in on of the instances ,
immediately 3 other instances become logged in as well.
Is it possible to achieve somehow in Current version that we got from Nuget ?
As of revision 2040, CEF now adds support for complete isolation of storage and permissions (cache, cookies, localStorage, access grants, etc) on a request context basis. This is also now in CEFSharp.
To make sure that no sessions overlap between multiple instances, simply create a new RequestContextSettings object, set PersistSessionCookies and/or PersistUserPreferences to false, and assign it to your browser while creating a new RequestContext - I am not sure if setting them to false is completely necessary for multiple instances, maybe someone else can give some info on that.
//usually ChromiumWebBrowser setup goes above this
RequestContextSettings requestContextSettings = new RequestContextSettings();
requestContextSettings.PersistSessionCookies = false;
requestContextSettings.PersistUserPreferences = false;
webBrowser.RequestContext = new RequestContext(requestContextSettings);
This had been giving me headaches for a while and this appears to finally solve that issue.
Just use this code, its working for me.
public MainWindow()
{
CefSharp.CefSettings settings = new CefSharp.CefSettings();
settings.CachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\CEF";
CefSharp.Cef.Initialize(settings);
InitializeComponent();
browser = new ChromiumWebBrowser("https://google.com/");
browser.BrowserSettings.ApplicationCache = CefSharp.CefState.Disabled;
}

Quartz.net configuration and scheduling

I have a WPF application where the user creates entities in the database. Each entity has some metadata and an interval field. For each entity I want to create a job with the interval provided and store them in the AdoJobStore.
Now since the WPF app will not always be running, I want a create a Windows Service that reads the jobs data from the AdoJobStore and run those jobs.
So essentially there are these 2 tiers. Now I have setup the Quartz tables already in my existing database. My question is:
How to create/edit/delete jobs from my WPF application
How to inform my windows service to run the jobs (every time an entity is created in database)
I have read through a lot of blogs but these 2 primary questions are a bit unclear to me. I would really appreciate some example code on how to achieve and may be structure my solution.
Thanks
You use Zero Thread Scheduler to schedule jobs. Example scheduler initialization code:
var properties = new NameValueCollection();
properties["quartz.scheduler.instanceId"] = "AUTO";
properties["quartz.threadPool.type"] = "Quartz.Simpl.ZeroSizeThreadPool, Quartz";
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
properties["quartz.jobStore.useProperties"] = "true";
properties["quartz.jobStore.dataSource"] = "default";
properties["quartz.jobStore.tablePrefix"] = tablePrefix;
properties["quartz.jobStore.clustered"] = "false";
properties["quartz.dataSource.default.connectionString"] = connectionString;
properties["quartz.dataSource.default.provider"] = "SqlServer-20";
schedFactory = new StdSchedulerFactory(properties);
BaseScheduler = schedFactory.GetScheduler();
Example scheduling function:
protected ITrigger CreateSimpleTrigger(string tName, string tGroup, IJobDetail jd, DateTime startTimeUtc,
DateTime? endTimeUtc, int repeatCount, TimeSpan repeatInterval, Dictionary<string, string> dataMap,
string description = "")
{
if (BaseScheduler.GetTrigger(new TriggerKey(tName, tGroup)) != null) return null;
var st = TriggerBuilder.Create().
WithIdentity(tName, tGroup).
UsingJobData(new JobDataMap(dataMap)).
StartAt(startTimeUtc).
EndAt(endTimeUtc).
WithSimpleSchedule(x => x.WithInterval(repeatInterval).WithRepeatCount(repeatCount)).
WithDescription(description).
ForJob(jd).
Build();
return st;
}
Obviously, you'll need to provide all relevant fields in your UI and pass values from those fields into the function. Example screenshot of some of the required fields:
Your Windows Service will initialize a Multi Thread Scheduler in OnStart() method in a very similar fashion to the way that Zero Thread Scheduler was initialized above and that Multi Thread Scheduler will monitor all the triggers in your database and start your jobs as specified in those triggers. Quartz.net will do all the heavy lifting in that regard. Once you scheduled your jobs and triggers are in the database all you need to do is initialize that Multi Thread Scheduler, connect it to the database containing triggers and it will keep on firing those jobs and execute your code as long as the service is running.

How can I create a webdriverjs promise without creating a webdriver instance?

I need to do some node require commands in a webdriverJS test script, because these dont get entered into the webdriverJS command queue, I am wrapping them in .then() functions (to deal with the asyncrony)
e.g.
var webdriver = require('selenium-webdriver');
// create webdriver instance so promise chain can be setup
var promise_builder = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).
build();
// wrap all functions in webdriver promises so they get managed by webdrivers
// command queue
promise_builder.sleep(0).then(function() {
// Run "non-command-queue" commands
var tests = require('./test_commands');
tests(helpers, setup, webdriver, driver);
}).then(function(){
// more non-webdriver commands
});
The problem here (other than the fact its inelegant) is that a browser instance is launched - just to achieve promise chaining.
Is there a better way to create the initial promise, e.g. a static method within the webdriver api for creating promises?
This seems to work:
// create an instance of webdriver.promise.ControlFlow
var flow = webdriver.promise.controlFlow();
// use webdriver.promise.controlFlow#execute() to schedule statements into command queue
flow.execute(function() {
// Run "non-command-queue" commands
var tests = require('./test_commands');
tests(helpers, setup, webdriver, driver);
}).then(function(){
// more non-webdriver commands
});
An explantion can be found on this Webdriver JS website/docs site, i.e.
At the heart of the promise manager is the ControlFlow class. You can obtain an instance of this class using webdriver.promise.controlFlow(). Tasks are enqueued using the execute() function. Tasks always execute in a future turn of the event loop, once those before it in the queue (if there are any) have completed.
I would use webdriver.promise.createFlow(callback) to start a new control flow.
So you'd have something like this:
webdriver.promise.createFlow(function() {
// Run "non-command-queue" commands
var tests = require('./test_commands');
tests(helpers, setup, webdriver, driver);
}).then(function(){
// more non-webdriver commands
});
Documentation: http://selenium.googlecode.com/git/docs/api/javascript/namespace_webdriver_promise.html
Update
I am now leaning towards the webdriver.promise.controlFlow.execute() option that #the_velour_fog described, since I get errors with after hook failing when new controlFlow is created. Guess creating a new flow messes with mocha async functionality.

Return multiple tables in one SQL Connection using Entity Framework

When i use Entity Framework Profiler the following code makes 3 calls to the database.
using (var entities = new Entities())
{
var faqs = entities.Table1.ToList();
var latest = entities.Table2.ToList();
var inst = entities.Table3.ToList();
}
I would like to make one database call, is there anyway to do this without calling a stored procedure?
I am trying to eliminate database calls throughout my application.
You can do a cross join in ef,
See this
http://geekswithblogs.net/berthin/archive/2012/05/25/how-to-perform-cross-join.aspx
My problem was solved by using the nuget package EntityFramework.Extended.
So using my original code, this is how you would solve my issue.
using (var entities = new Entities())
{
var faqs = entities.Table1.Future();
var latest = entities.Table2.Future();
var inst = entities.Table3.Future();
inst.ToList();
}
When you call ToList() a batch call is sent to your database in one connection.
The reference link is below:
https://github.com/loresoft/EntityFramework.Extended/wiki/Future-Queries

Resources