Aborting a change to a node from a module - file

I'm building a module for Drupal 6 (what it does isn't wildly important; I've spent a long time looking for other solutions to this problem and rolling my own is definitely the simplest), and I've run into something of a conceptual road-block.
Much like the uploadpath module, I'm creating a directory based on (via a replacement pattern) properties of a node. For instance, creating a node with the "assignmentindex" contenttype called "Foobar", my module will create a folder sites/default/files/assignmentindex/Foobar.
The problem comes (predictably) during update events, when the target directory already exists, or can't be created for some other strange reason (the only one I can dream up right now is running out of inodes, but I'm sure there are other failure conditions). Obviously, to avoid losing data, the original folder needs to be left alone, but that breaks the association between the directory and the node. Thus, I see 3 different possibilities:
Rolling back the whole node
Rolling back just the changed title
Not rolling anything back (but showing an error)
First question is which of these is best? Rolling back the whole node wipes away a potentially huge amount of work, rolling back just the title is confusing and rolling back nothing means that the names are out of sync. My current preference is for just rolling back the title, but I'd really appreciate thoughts on this.
The second question is: how? I've already switched the relevant $op to presave (from update) so that the original node is available via
$old_node = node_load($node->id);
and to roll back a single field, can potentially just do
$node->title = $old_node-title;
but this seems sub-optimal, and I'm curious as to whether there's a better way of achieving this.
Sorry for the long question, and many thanks in advance for your help.

As an alternative to those discussed above: if you do not care about imported/programmatically created nodes, you could add a validation handler on the node form submission. Validation has access to both the new and old nodes, and can reject the submission to the user in a more standard fashion.
function custom_form_alter(&$form, &$form_state, $form_id) {
if ($form['#id'] == 'node-form') {
$form['#validate'][] = '_custom_node_form_validate';
}
}
function _custom_node_form_validate(&$form, &$form_state) {
$old_node = $form['#node'];
$new_node = $form_state['values'];
}

Related

How to set a level of confidence for watson conversation?

I would like to understand how to create a way to redirect the conversation to the anything_else node when confidence is lower then a established limit.
I am creating a node triggered by intents[0].confidence < 0.5 that jumps to the anything_else answer.
So if I enter a value "huaiuhsuskunwku" it recognizes as the intent #greetings and do redirect its node.
Any idea why it is recognizing it as a greeting in the first place?
And how can I configure it properly?
Two things here:
1a. Before the newest API was released, which is still beta, we used what is called a relational classifier. Meaning it checks all the classes available, and will do its best to fit it into the most similar one. So I would assume you have relatively few intents, and each intent has only a handful of samples. There are too many features in the algorithm to point to one specifically, but its finding some features that make it think it is part of that class.
1b. You should create a class for off-topic that just includes a bunch of things you dont want to respond to. This essentially helps balance out the existing classes so it knows it is NOT your main classes. You wont need any dialog nodes for this, the off-topic class simply helps it fall to anything else as you want
2. Just this week we have released an update to the API. This changes it to an absolute classifier so scoring is handled differently now. Each class is evaluated on its own. We have also included a built in off-topic handler to help weed out gibberish like this. See the docs here:
https://www.ibm.com/watson/developercloud/doc/conversation/release-notes.html
Watson follows Top to Bottom Flow. So there may be 2 cases.
Your Greeting node is above to the one which you created for routing to Anything else and that your query's (huaiuhsuskunwku) confidence was >=0.20 for #greeting intent. In this case just move your greetings dialog below to the node you created.
If your greeting dialog is below to the node you created for routing to Anything else dialog. The given condition(confidence < 0.5) failed and thus skipped that dialog. In this case, check the confidence of that query in 'Try it' window and adjust confidence value in dialog accordingly.

Keeping repository synced with multiple clients

I have a WPF application that uses entity framework. I am going to be implementing a repository pattern to make interactions with EF simple and more testable. Multiple clients can use this application and connect to the same database and do CRUD operations. I am trying to think of a way to synchronize clients repositories when one makes a change to the database. Could anyone give me some direction on how one would solve this type of issue, and some possible patterns that would be beneficial for this type of problem?
I would be very open to any information/books on how to keep clients synchronized, and even be alerted of things other clients are doing(The only thing I could think of was having a server process running that passes messages around). Thank you
The easiest way by far to keep every client UI up to date is just to simply refresh the data every so often. If it's really that important, you can set a DispatcherTimer to tick every minute when you can get the latest data that is being displayed.
Clearly, I'm not suggesting that you refresh an item that is being edited, but if you get the fresh data, you can certainly compare collections with what's being displayed currently. Rather than just replacing the old collection items with the new, you can be more user friendly and just add the new ones, remove the deleted ones and update the newer ones.
You could even detect whether an item being currently edited has been saved by another user since the current user opened it and alert them to the fact. So rather than concentrating on some system to track all data changes, you should put your effort into being able to detect changes between two sets of data and then seamlessly integrating it into the current UI state.
UPDATE >>>
There is absolutely no benefit from holding a complete set of data in your application (or repository). In fact, you may well find that it adds detrimental effects, due to the extra RAM requirements. If you are polling data every few minutes, then it will always be up to date anyway.
So rather than asking for all of the data all of the time, just ask for what the user wants to see (dependant on which view they are currently in) and update it every now and then. I do this by simply fetching the same data that the view requires when it is first opened. I wrote some methods that compare every property of every item with their older counterparts in the UI and switch old for new.
Think of the Equals method... You could do something like this:
public override bool Equals(Release otherRelease)
{
return base.Equals(otherRelease) && Title == otherRelease.Title &&
Artist.Equals(otherRelease.Artist) && Artists.Equals(otherRelease.Artists);
}
(Don't actually use the Equals method though, or you'll run into problems later). And then something like this:
if (!oldRelease.Equals(newRelease)) oldRelease.UpdatePropertyValues(newRelease);
And/Or this:
if (!oldReleases.Contains(newRelease) oldReleases.Add(newRelease);
I'm guessing that you get the picture now.

CakePHP afterSave Timing

I have a situation where, in a model's afterSave callback, I'm trying to access data from a distant association (it's a legacy data model with a very wonky association linkage). What I'm finding is that within the callback I can execute a find call on the model, but if I exit right then, the record is never inserted into the database. The lack of a record means that I can't execute a find on the related model using data that was just inserted into the current.
I haven't found any mention of when data is actually committed with respect to when the afterSave callback is engaged. I'm working with legacy code, but I see no indication that we're specifically engaging transactions, so I'm trying to figure out what my options might be.
Thanks.
UPDATE
The gist of the scenario is this: We're taking event registrations, but folks can be wait listed. A user can register (or be registered) for a given Date. After a registration is complete, I need to check the wait list for the existence of a record for the registering user (WaitList.user_id) on the date being registered for (WaitList.date_id). If such a record exists, it can be deleted because it's become an active registration.
The legacy schema puts me in a place where the registration isn't directly tied to a date so I can't get the Date.id easily. Instead, Registration->Registrant->Ticket->Date. Unintuitive, I know, but it is what it is for now. Even better (sarcasm included), we have a view named attendees that rolls all of this info up and from which I would be able to use the newly created Registration->id to return Attendee.date_id. Since the record doesn't exist, it's not available in the view.
Hopefully that provides a little more context.
What's the purpose of the find query inside of your afterSave?
Update
Is it at all possible to properly associate the records? Or are we talking about way too much refactoring for it to be worth it? You could move the check to the controller if it's not possible to modify the associations between the records.
Something like (in psuedo code)
if (save->isSuccessful) {
if (onWaitList) {
// delete record
}
}
It's not best practice, but it will get you around your issue.

database modeling for google app engine for multiple revison of entity

in my application ( kind of wiki clone ) - an article is frequently changing.
and i need to track all changes that are done on that article. { text only. }
one crude way i have done it, is to add a datetime property and create a new entity everytime something change. which is too much database wasting. { and also un-necessary index waste too. } and also need to re-create parent-child and entity relationships.
i also have log which can show changes -- but i want some thing easier , so that jumping from one version to another version could be easier.
ideas ?
thanks.
You could split the location in your wiki from the content, and link from there to the version of the page. Keep the versions in a linked list, doubly linked if you 2 way navigation, circular, whatever.
The parent child, indexing and so forth deal only with the location and the article linked to that.
Reverting to a previous change is only changing the link in the location (and pushing the changes to your indexing machine). Pruning are basic list operations, i.e. pointing the next field to a version further down and deleting the version in between.

Synchronizing Asynchronous request handlers in Silverlight environment

For our senior design project my group is making a Silverlight application that utilizes graph theory concepts and stores the data in a database on the back end. We have a situation where we add a link between two nodes in the graph and upon doing so we run analysis to re-categorize our clusters of nodes. The problem is that this re-categorization is quite complex and involves multiple queries and updates to the database so if multiple instances of it run at once it quickly garbles data and breaks (by trying to re-insert already used primary keys). Essentially it's not thread safe, and we're trying to make it safe, and that's where we're failing and need help :).
The create link function looks like this:
private Semaphore dblock = new Semaphore(1, 1);
// This function is on our service reference and gets called
// by the client code.
public int addNeed(int nodeOne, int nodeTwo)
{
dblock.WaitOne();
submitNewNeed(createNewNeed(nodeOne, nodeTwo));
verifyClusters(nodeOne, nodeTwo);
dblock.Release();
return 0;
}
private void verifyClusters(int nodeOne, int nodeTwo)
{
// Run analysis of nodeOne and nodeTwo in graph
}
All copies of addNeed should wait for the first one that comes in to finish before another can execute. But instead they all seem to be running and conflicting with each other in the verifyClusters method. One solution would be to force our front end calls to be made synchronously. And in fact, when we do that everything works fine, so the code logic isn't broken. But when it's launched our application will be deployed within a business setting and used by internal IT staff (or at least that's the plan) so we'll have the same problem. We can't force all clients to submit data at different times, so we really need to get it synchronized on the back end. Thanks for any help you can give, I'd be glad to supply any additional information that you could need!
I wrote a series to specifically address this situation - let me know if this works for you (sequential asynchronous workflows):
Part 2 (has a link back to the part1):
http://csharperimage.jeremylikness.com/2010/03/sequential-asynchronous-workflows-part.html
Jeremy
Wrap your database updates in a transaction. Escalate to a table lock if necessary

Resources