I try to wait until all running packages are finished on SQL Server after I started an SSIS package, but I cannot figure out the correct way to do it. The code I have so far is:
var runningPackagesBefore = catalog.Executions.ToList();
// [..] logic to start the package
while (true)
{
// get all packages that are new
catalog.Executions.Refresh();
var newOperations = catalog.Executions.Except(runningPackagesBefore);
// get all packages that are new, running and are in the same folder and project as the package
var runningOperations =
newOperations.Where(
operation => operation.FolderName == catalogFolder.Name
&& operation.ProjectName == project.Name
&& operation.Status == Operation.ServerOperationStatus.Running);
if (!runningOperations.Any())
{
break;
}
// [..] sleep and timeout logic here
}
The catalog.Executions.Refresh() call causes deadlock problems sometimes. The documentation also says "Do not reference this method directly...".
A refresh is needed because otherwise the executions collection is cached and returns 0 new transactions. And when it runs without deadlocks it returns the amount of running packages correctly.
So I am trying to find a way to see if all packages are finished running. The package I am running is a "master" package that starts multiple other packages. Otherwise I could simply get the Execution ID and get the operation state from the catalog, but that is not possible in this case.
Solved it by recalling the integrationservice and getting a new catalog. This refreshes it automatically:
// get all executions for this project that are currently running
var runningPackagesBefore = catalog.Executions.Select(operation => operation.Id).ToList();
// [..] logic to execute the package
while (true)
{
var integrationServices = new IntegrationServices(sqlConnection);
Catalog refreshedCatalog = integrationServices.Catalogs[catalogName];
// get all packages that are running
var runningOperations = refreshedCatalog.Executions.Where(
operation => operation.Status == Operation.ServerOperationStatus.Running);
// get all packages that are new
var newRunningOperations = runningOperations.Where(
operation => !runningPackagesBefore.Contains(operation.Id));
if (!newRunningOperations.Any())
{
break;
}
// [..] sleep and timeout logic here
}
Related
I'm attempting to retrieve some data from a Firebase database. I've been able to do it fine in the past, but there's something wrong with my GetValueAsync() code below. When debugging it gets stuck at the "await reference.Database" line, but I'm not sure what I'm doing wrong. When running without debugging, none of the information is ever retrieved.
I'm uncertain if the problem is with the path, or the await/async function. Debugging shows that loggedUserId is storing the value before referencing it in the next line, but the rest of the function never completes or faults. The application compiles but I'm never able to capture any info from the snapshot.
The format of my database is "users" -> 78cVqzA8qNTNigsao3VvdnM0Qol2 (Which is correct) -> (several data pairs such as level : 1, lives : 3, etc)
public static async void GetUserData()
{
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl("https://narwhaltrivia.firebaseio.com/");
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
DatabaseReference reference = Firebase.Database.FirebaseDatabase.DefaultInstance.RootReference;
loggedUserId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;
await reference.Database.GetReference("users").Child(loggedUserId).GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.LogError("Error retrieving user data");
return;
}
if (task.IsCompleted)
{
DataSnapshot userSnapshot = task.Result;
loggedEmail = userSnapshot.Child("email").GetRawJsonValue();
loggedCurrentScore = userSnapshot.Child("currentScore").GetRawJsonValue();
loggedLevel = userSnapshot.Child("level").GetRawJsonValue();
loggedLives = userSnapshot.Child("lives").GetRawJsonValue();
loggedRound = userSnapshot.Child("round").GetRawJsonValue();
loggedTotalScore = userSnapshot.Child("totalScore").GetRawJsonValue();
return;
}
});
}
I have created an app with in app purchase and tested it with CurrentAppSimulator and works fine but when i create the package for app it fails
This is my code for which i am creating package
public async System.Threading.Tasks.Task InAppInit()
{
var listing = await CurrentApp.LoadListingInformationAsync();
// Delux Unlock - Durable
var unlockFeatureDelux = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "deluxe" && p.Value.ProductType == ProductType.Durable);
isDeluxPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureDelux.Value.ProductId].IsActive;
deluxProductID = unlockFeatureDelux.Value.ProductId;
// Standard Unlock - Durable
var unlockFeatureStandard = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "standard" && p.Value.ProductType == ProductType.Durable);
isStarndardPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureStandard.Value.ProductId].IsActive;
standardProductID = unlockFeatureStandard.Value.ProductId;
}
I am calling this method OnLaunched in App.xaml.cs
Based on our discussion here is what I would do:
The LoadListingInformationAsync method uses internet and if the user does not have an internet connection then it will throw an exception. So I suggest to wrap this whole stuff into a try/ctach block
As we see the ProductListings does not contain any item. I don't know how this list is populated, but as long as your app is not in the store I would not be surprised when that list is empty (Maybe someone can help out here... but i did not find anything regarding this in the docs). So for this I would just simply check if the feature you need is in the list... With this your package will pass the test you mentioned and you can upload it. If the list is also empty when the package is installed via the store, then something with the IAP setting is wrong (but that is related to the store..)
And a general comment: Obviously this code is not complete... You need some code for purchasing the IAPs and here we only get the Ids.. (But I think you only pasted the relevant part anyway.)
So all this in code:
public async System.Threading.Tasks.Task InAppInit()
{
try
{
var listing = await CurrentApp.LoadListingInformationAsync();
if (listing.ProductListings.ContainsKey("deluxe"))
{
// Delux Unlock - Durable
var unlockFeatureDelux = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "deluxe" && p.Value.ProductType == ProductType.Durable);
isDeluxPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureDelux.Value.ProductId].IsActive;
deluxProductID = unlockFeatureDelux.Value.ProductId;
}
else
{
//There is no deluxe IAP defined... so something with your IAP stuff is wrong...
}
if (listing.ProductListings.ContainsKey("standard"))
{
// Standard Unlock - Durable
var unlockFeatureStandard = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "standard" && p.Value.ProductType == ProductType.Durable);
isStarndardPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureStandard.Value.ProductId].IsActive;
standardProductID = unlockFeatureStandard.Value.ProductId;
}
else
{
//same as for Delux
}
}
catch
{
//Show this on the UI...
}
}
I'll try to explain the issue with a simplified console application example, however the real project is a ASP.NET MVC3 application.
Having the following tables:
imagine the following scenario:
user creates a report (a line in TestReport, where Text is the report string content, and Ready is a bool flag, saying, if the report is ready to be processed); by default Ready is set to false, i.e. not ready.
user wants the report to be processed, so he submits it; Ready is set to true here.
The system gives an opportunity to recall the report back, if it has not been processed yet. So, when the report is recalled, Ready is set to false back. On the contrary, when the report is processed, a line in TestReportRef, referencing report by its Id, is created.
Now imagine that at one and the same moment
user wants to recall the report;
the report is added to the process list;
As soon as this can happen simultaneously, errors may occur. That is the report will have Ready == false and it'll be referenced in TestReportRef.
Here is a simple console example of how this may happen:
var dc = new TestDataContext('my connection string');
dc.TestReport.InsertOnSubmit(new TestReport
{
Text = "My report content",
Ready = true //ready at once
});
dc.SubmitChanges();
Action recallReport = () =>
{
var _dc = new TestDataContext(cs);
var report = _dc.TestReport.FirstOrDefault(t => t.Ready);
if (report != null && !report.TestReportRef.Any())
{
Thread.Sleep(1000);
report.Ready = false;
_dc.SubmitChanges();
}
};
Action acceptReport = () =>
{
var _dc = new TestDataContext(cs);
var report = _dc.TestReport.FirstOrDefault(t => t.Ready);
if (report != null && !report.TestReportRef.Any())
{
Thread.Sleep(1000);
_dc.TestReportRef.InsertOnSubmit(new TestReportRef
{
FK_ReportId = report.Id
});
_dc.SubmitChanges();
}
};
var task1 = new Task(recallReport);
var task2 = new Task(acceptReport);
task1.Start();
task2.Start();
task1.Wait();
task2.Wait();
foreach (var t in dc.TestReport)
{
Console.WriteLine(string.Format("{0}\t{1}\t{2}", t.Id, t.Text, t.Ready));
}
foreach (var t in dc.TestReportRef)
{
Console.WriteLine("ref id:\t" + t.FK_ReportId);
}
Thread.Sleep(1000); is added to be ensure, that tasks will check one and the same situation.
The given example may sound awkward, however, I hope, it should explain the issue I'm dealing with.
How can I avoid this? Making the repository singleton doesn't seem to be a good idea. Shall I use some shared mutex (one for all web requests) to separate write-operations only?
Or is there a pattern I should use in this kind of scenario?
This is only a simplified example of one of the scenarios I have. However, there are several scenarios in which it may run into a similar discrepancy. The best thing would be to make this kind of intersection impossible, I guess.
Why don't add a version column on the Report table? Task starts by tracking current version,when task end, if the version is the same that the tracked one, operation is ok, otherwise fail. If operation appear ok, update the version to version +1. This is a sort of optimistic lock; that implicitly suppose that conflicts may occur, but they are not so frequent.
UPDATE
If you are using linqto sql maybe you can have a check at the parameter UpdateCheck [Column(UpdateCheck=UpdateCheck.Always)]
This can be useful to handle concurrency in your case.
I'm using Quartz to pull latest tasks (from another source), it then adds it in as a job, creates triggers etc per each task. - Easy.
However, sometimes tasks change (therefore they already exist). Therefore I would like to change its (lets say to keep it simple Description. Code below updates specific task's description with given date.
private static void SetLastPull(DateTime lastPullDateTime)
{
var lastpull = sched.GetJobDetail("db_pull", "Settings");
if(lastpull != null)
{
lastpull.Description = lastPullDateTime.ToString();
}
else
{
var newLastPull = new JobDetail("db_pull", "Settings", typeof(IJob));
newLastPull.Description = lastPullDateTime.ToString();
var newLastPullTrigger = new CronTrigger("db_pull", "Settings", "0 0 0 * 12 ? 2099");
sched.ScheduleJob(newLastPull, newLastPullTrigger);
}
}
I'm assuming after I do lastpull.Description = lastPullDateTime.ToString(); I should call something to save changes to database. Is there a way to do it in Quartz or do I have to go to using other means and update it?
You can't change (update) a job once it has been scheduled. You can only re-schedule it (with any changes you might want to make) or delete it and create a new one.
I'm using the IronCow managed API for RememberTheMilk (http://ironcow.codeplex.com/) and I'm trying to remove tasks using my program. I've already logged in and downloaded the tasks list, but when I later try to remove one I get the following exception:
[IronCow.RtmException] = {"User not logged in / Insufficient permissions"}
I'm removing tasks using this code (rtm is my logged in RTM object, myTask is the Task object I'm looking to delete)
TaskListCollection tlc = rtm.TaskLists;
foreach (TaskList list in tlc)
{
TaskListTaskCollection taskListsTasks = list.Tasks;
foreach (Task task in taskListTasks)
{
if (!(task.IsDeleted || task.IsCompleted) && task.Name == myTask.Name)
{
list.Tasks.Remove(task);
}
}
}
the line it errors on is list.Tasks.Remove
Discovered it was a permissions problem due to permissions being stored from an old version of the app that didn't need to delete