I have been hitting my head off a wall on this for the last 3 days.
I am using sailsjs & the waterline ORM that comes bundled. I want to run DB calls one after an other. I know I can do this by nesting inside "then" calls but it just looks wrong.
I have gone over the Q documentation and tutorials several times but I still don't get how to connect and fire "then" calls from existing Promises sequentially :(
I want to:
create a user
create a action
link the user & action
update the user
update the action
My code looks like
var mail = 'test#test.com';
Users.create({email:mail, name:''}).then(console.log).fail(console.log);
Actions.create({actionID:123})
.then(function(error, action){
Users.findOneByEmail(mail).then(function(person){
person.actions.add(action.id);
person.save(console.log);
}).fail(console.log)
});
Users.update({email:mail},{name:'Brian'}).exec(console.log);
Actions.update({actionID:123},{now:'running'}).exec(console.log);
As you can see from the code I've been using a mix of exec & then :P
I think the way is to connect the
Users.create(...).then -> Action.create(...).then -> Users.findOneByEmail(...).then -> *and the updates.
Huge thanks from any help
So after a day's research. I think I've cracked it.
Note: The first version I got working had the "then"s lined-up(removing the pyramid of doom) by returning the create. This allow me to call then on the next line to fire the create. http://documentup.com/kriskowal/q/#tutorial/chaining
Here's my final version
var mail = 'test#test.com';
Users.Create({email:mail,name:''})
.then(function(user){
return [Actions.create({actionID:123}),user];
}).spread(function(action, user){
user.action.add(action.id);
user.name = 'Brian';
user.save();
action.now = 'running';
action.save();
}).catch(console.error);
One of the cool things is the "spread" that allows you to line-up "Promises" and "values" to be return one they all have completed into the next "then".
Related
I created a script which updates work items in a polarion document. However, right now each workitem update is a single save. But my script updates all work items in the document, which results in a large number of save actions in the api and thus a large set of clutter in the history.
If you edit a polarion document yourself, it will update all workitems.
Is it possible to do this same thing with the polarion API?
I tried
Using the tracker service to update work items. This only allows a single work item to be updated.
Using the web development tools to try and get information from the API. This seems to use a UniversalService for which no documentation is available at the API site https://almdemo.polarion.com/polarion/sdk/index.html
Update 1:
I am using the python polarion package to update the workitems.Python polarion Based on the answer by #boaz I tried the following code:
project = client.getProject(project_name)
doc = project.getDocument(document_location)
workitems = doc.getWorkitems()
session_service = client.getService("Session")
tracker_service = client.getService("Tracker")
session_service.beginTransaction()
for workitem in workitems:
workitem.description = workitem._polarion.TextType(
content=str(datetime.datetime.now()), type='text/html', contentLossy=False)
update_list = {
"uri": workitem.uri,
"description": workitem.description
}
tracker_service.updateWorkItem(update_list)
session_service.endTransaction(False)
The login step that #boaz indicated is done in the backend (See: https://github.com/jesper-raemaekers/python-polarion/blob/3e61527cf0f1f3c8614a30289a0a3409d2d8712d/polarion/polarion.py#L103)
However, this gives the following Java exception:
java.lang.RuntimeException: java.lang.NullPointerException
Update 2
There seems to be an issue with the session. If I call the following code:
session_service.logIn(user, password)
print(session_service.hasSubject())
it prints False.
The same thing happens when using the transaction:
session_service.beginTransaction()
print(session_service.transactionExists())
also prints False
Try wrapping your changes in a SessionWebService transaction, see JavaDoc:
sessionService = factory.getSessionService();
sessionService.logIn(prop.getProperty("user"),
prop.getProperty("passwd"));
sessionService.beginTransaction();
// ...
// your changes
// ...
sessionService.endTransaction(false);
sessionService.endSession();
As shown in the example in Polarion/polarion/SDK/examples/com.polarion.example.importer.
This will commit all your changes in one single SVN commit.
In our web application, we observed the following:
GetUser/CreatMembershipEntities/ExplicitLoadFromAssembly seems quite expensive.
Also noticing that CreateEntityConnection is being called - EntityFramework?
I'm not entirely convinced that EF was configured correctly for this application. If it was, and was in use, I wouldn't expect to see new connections to be initiated for every call - yes/no?
Is a way to streamline this to avoid some major code refactoring?
The use of System.Web.Security.Membership.GetUser() seems like a biggie here. Instead of using the MembershipProvider to create users, what about just executing a sproc that does the same things.
I have found the following code that is ridiculous, as far as I am concerned - in causing a new call for each user until a unique one can be generated:
For i As Integer = 1 To Integer.MaxValue
'Generate unique username
If System.Web.Security.Membership.GetUser(userName & i) Is Nothing Then
'Increment value until no duplicate username found
userName = userName & i
Exit For
End If
Next
-- UPDATE--
I have modified the question slightly...
We were able to run up to 20 users then the IIS server would tank. Does the GetUser() method create a brand new connection every time? It looks like it, based on the results. How can I ensure that this GetUser() thing is actually using the db context, rather than spinning up its own connections?
Few month back I was working on some Odata WCF project and I had some problems with parsing custom headers for token auth (apiKey).
At that time, being quite a noob (still am!), I posted this SO question: JayData oData request with custom headers
Today I am working on a new project with Jaydata Odata server and client library and this:
application.context.prepareRequest = function (r) {
r[0].headers['apikey'] = '123456';
};
was working fine till I had to do a MERGE request. I found out that somehow MERGE request was overriding my headers so I investigated further.
It appears at first that in the oDataProvider.js (~line 617) in the _saveRest method the headers are not inherited:
request = {
requestUri: this.providerConfiguration.oDataServiceHost + '/',
headers: {
MaxDataServiceVersion: this.providerConfiguration.maxDataServiceVersion
}
};
but a few lines later we get:
this.context.prepareRequest.call(this, requestData);
which "should" call my own prepareRequest, but doesnt... Instead it still points to:
//Line 11302 jaydata.js
prepareRequest: function () { },
which of course does... nothing! Funnilly enough, when you execute a simple GET the same code supposedly on the same context instance works and points to my prepareRequest override.
I can assert with enough confidence that somehow the context between GET/MERGE is not the same instance. I cant see, however, any place where the context instance is reassigned.
Has anyone got a clue?
PS: this is NOT a CORS issue. My OPTIONS is passing fine and manually feeding the headers in oDataProvider works.
More
I followed the lead on different context instances and found something interesting. calling EntitySet.save() ends up calling the EntityContext constructor. see trace:
$data.Class.define.constructor (jaydata.js:10015)
EntityContext (VM110762:7)
Service (VM110840:8)
storeToken.factory (jaydata.js:14166)
$data.Class.define._getContextPromise (jaydata.js:13725)
$data.Class.define._getStoreContext (jaydata.js:13700)
$data.Class.define._getStoreEntitySet (jaydata.js:13756)
$data.Class.define.EntityInstanceSave (jaydata.js:13837)
$data.Entity.$data.Class.define.save (jaydata.js:9774)
(anonymous function) (app.js:162) // My save()
That explains why I get two different instances...
Hack
Replacing the prepareRequest function direcly in the class definition works, but its ugly!
for now I can cope with this:
$data.EntityContext.prototype.prepareRequest = function (r) {
r[0].headers['apikey'] = '12345';
};
This works fine as long as you only need to talk to a single endpoint.
Final word based on my experience
As much as I like JayData, it is obvious that they created a monster and its getting out of their hands (poor forum, no community, half-documented,...).
I chose JD because I was lazy and wanted to keep working with my old WCF DataService. Switching to Web API seemed wrong or too much work for me.
Also as a .net dev I liked strong typing of my entities and the ability to work with a concrete model generated from the JD tools. However, in the end, I was adding confusion. Every time my server side model changed I had to fetch the new metadata and scaffold a new entityModel.
I ended up by switching to Web Api and migrated my data service layer to Breeze. And seriously! its a breeze to work with it!
The documentation is absolutely brilliant and here on S.O you can always count on Ward or Jay Tarband to reply with a very high amount of professionalism.
In the end I realize this should probably be more a wiki than a Question.....
I have a form with a listview in it that the user can add tasks too. Then the user can click a button then the application goes through each task in the listview 1 by 1 an executes it.
These tasks are more like instructions that actually complete tasks.I do this by having a class with a loop in it that goes through each item and it then completes a task I set for each item(instruction). In order to start the parsing I have a button on a form that calls that function. IE: RunTask(listview1, 1) - basically all this does it starts the loop I have in my class , with a specified listview and which item to start on.
Everything works perfect except the screen locks up, so I cannot implement a stop feature to stop the application from parsing these listview items. I just don't understand how I can implement this without crossthreading, since the thread that I would like to run seperate will always access this listview. It is not feasable to redesign the program to get rid of the listview. I tried application.doevents although it caused way too man bugs. I have been researching for days on how to fix this but I have NO idea. Hopefully someone cans hed some light.
Also I had already added a background worker to solve the issue, although I had to obviously set checkforillegalcrossthreadcalls = false and I know this isn't smart.
Try doing something like this. Take you list view and turn it into a set of values that aren't UI related. Like this:
string[] values =
this
.listView1
.Items
.Cast<ListViewItem>()
.Select(x => x.Text)
.ToArray();
Then you can use the parallel task library to run your task in the background:
var tokenSource = new System.Threading.CancellationTokenSource();
var token = tokenSource.Token;
var task = System.Threading.Tasks.Task.Factory
.StartNew(() => RunTasks(values, 1), token);
If you need to cancel the task you can do this:
tokenSource.Cancel();
But to handle UI updates when the task is finished do this:
task.ContinueWith(r =>
{
/* When compete code */
});
Make sure that you invoke the UI updates so that they go on the UI thread.
My apologies that I didn't write this in VB.NET. My VB is getting rusty.
I'm using Symbian C++ to create my code, I'm using S60 5th Ed SDK
I want to know how to send different messages - Their body text not the same - to multiple recipients in a for-loop ?
I've tried the example below, but when I try to use it in a loop it crashes due to ActiveObjects properties, as I should wait to AO to finish before calling it again.
Sending_SMS_in_S60_3rd_Edition_MTM
Below is example of what I need to do:
SendSMSL(); // **I call this function once to start the process**
// **iRecepients is a CDesCArray contains phone numbers**
// ** iSMSBody is a CDesCArray contains each contact SMS body text**
void CSMS::SendSMSL()
{
if(iRecepients->Count() >= 1)
{
TInt x = iRecepients->Count()-1;
TInt y = iSMSBody->Count()-1;
// **If the sms validating and scheduling succeeded then delete last item from both arrays**
if(iSMSHandler->SendL((*iRecepients)[x],(*iSMSBody)[y])
{
iRecepients->Delete(x);
iSMSBody->Delete(y);
}
}
}
Now, in the code above I call iSMSHandler->SendL() which send sms using AO, and in iSMSHandler object RunL() function, I call back the function above CSMS::SendSMSL() , which in turn checks if there is still anymore iRecepients elements and then call again iSMSHandler->SendL() AO , and keeps this way till no more iRecepients.
Looking forward to hear your feedback on the modification above.
Many thanks in advance.
The link you posted doesn't work for me so I can't see the rest of the code.
Assuming that iSmsHandler is a class that uses active objects to send SMS messages,
I see several issues with your loop.
1) You need to wait for the first asynchronous SendL to complete before you can issue the next SendL
2) The buf variable can not go out of scope until the SendL completes. (This may be the reason for your crash)
I suggest that you keep the textbuffer somewhere else, like together with iSmsHandler, and then code the active object that is called when SendL completes to issue the next SendL.
All of this is guesses since I have no idea what class iSmsHandler is....