Tridion Event System Timeout - tridion

I am currently running Tridion 2011 SP1.
I am writing some code that runs whenever a page is published. It loops through each component template in the page, gets the component and writes out various fields to an XML document. For pages with many component templates or components with many fields this process can take a while to run. If the process takes more than 30 seconds I get an error
The operation performed by thread "EventSystem0" timed out.
Component: Tridion.ContentManager
Errorcode: 0
User: NT AUTHORITY\NETWORK SERVICE
followed by another
Thread was being aborted.
Component: Tridion.ContentManager
Errorcode: 0
User: NT AUTHORITY\NETWORK SERVICE
StackTrace Information Details:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at Tridion.ContentManager.Extensibility.EventSubscription.DeliverEvent(IEnumerable`1 subjects, TcmEventArgs eventArgs, EventPhases phase)
I believe I have three options.
1. Increase the timeout
This seems like a lazy solution and only hides the problem. There is no guarantee that the timeout problem won't reoccur. I'm also not sure where the timeout value is stored (I've tried changing a few values in the Tridion Content Manager.msc snap-in but no luck).
2. Do less in the actual event handler routine and have a separate process do all the hard work
This doesn't seem like the correct solution either. I would really like to keep all my event handler code in the one place. We have a solution like this in place for our live 5.3 installation and is a nightmare to maintain (it is very old and poorly written).
3. Make my code more efficient
My components have many fields and my code must delve deeper into each field if they are ComponentLinks. I guess because the properties of Tridion objects are lazy loaded there is one call to the API/database for each property I access. It takes on average 0.2 seconds to retrieve a property which soon stacks up when accessing multiple properties. If there was a way to retrieve all properties in one call this would be useful.
Any ideas?

Have you considered running your event asynchronously? You can do this by changing the following line:
EventSystem.Subscribe<IdentifiableObject,TcmEventArgs(....)
to
EventSystem.SubscribeAsync<IdentifiableObject,TcmEventArgs(....)

One thing you might consider doing is using the Component's .ToXml() method and get your values from the XML DOM instead of using the Tridion API. This is usually considerably faster, and you can use XSLT or Linq to "walk" through your fields.
If you are really only interested in fields, then just use the .Content (and .Metadata) properties and, again, use Linq or XSLT or whatever technology you want to parse the xml (except RegEx perhaps).

You are simply doing a lot of processing and that takes time. Maybe there's a technical fix, but the first thing to do in this situation is to go back to Why and What? Publishing a page is fundamentally about rendering the HTML and binaries that you want to output for that page. How long should that take?
So please could you tell us why you are doing this? Perhaps part of the effort can be moved somewhere else without compromising on good design. If we know what the purpose is, perhaps we can help more.

SDL Customer Support have advised that I increase the timeout. While not a great solution its the only one that is available. To do this
On the server that the content manager is installed open the Tridion.ContentManager.config which should be located in the config/ subdirectory of the Content Manager root location, which defaults to C:\Program Files\Tridion\ or c:\Program Files (x86)\Tridion\
Find the <eventSystem> node
Increase the threadtimeout value (this is in seconds) to something higher (I put it to 120)
Save the Tridion.ContentManager.config and restart the Tridion Content Manager Service Host service
Further documentation is available http://sdllivecontent.sdl.com/LiveContent/web/pub.xql?action=home&pub=SDL_Tridion_2011_SPONE&lang=en-US#addHistory=true&filename=ConfiguringEventSystem.xml&docid=concept_48C53F76CBFD45A783A3975CA72ECC49&inner_id=&tid=&query=&scope=&resource=&eventType=lcContent.loadDocconcept_48C53F76CBFD45A783A3975CA72ECC49. It does require a username and password to access.

If you really need the processing time then I think you should write a web service that performs the actions you need, which you can call from the event handler. This would not influence user experience (in the case of a synchronous event handler) as much either.

Related

OpenLaszlo 4.9 DHTML login servlet forwards but never loads page

I am having some problems at the moment using a LoginServlet running OL 4.9, on Tomcat 7.
I have Tomcat configured to allow crossContext to be true, and that allows me to work with other app contexts on the same server. Specifically a Login Servlet. My only other app is the OpenLaszlo presentation server LPS(lps-4.9.0).
I am using a Tomcat Request Filter that snoops the incoming addresses and looks for a particular cookie of authentication, which then makes its way to the LoginServlet that does a forwarding to the OpenLaszlo page. This was done to KEEP the cookie alive when the Request Filter was awakened at the loading of the OpenLaszlo page.
All of that is working now.
There are no errors or warnings in the lps.log file or the localhost.<date>.log either, however the page loading goes on forever, and never completes.
Could it be something that I am passing along in the forwarded URL? I am using at least 2 parameters to cause lzr to be set to "dhtml" and then lzt to be set to "html."
I can't even get a simple <canvas> page with a simple button to load. Has anyone seen this, and been able to fix the problem?
Since I first wrote my description I wrote another plea for help to some friends and ex coworkers, and this will help update the details of what I have discovered thus far.
Here’s the scenario: I am using Tomcat 7, and have installed the WAR file for OpenLaszlo 4.9.
Alongside of this I created a LoginServlet hierarchy and code and web.xml file just under
“webapps”; the same level that lps-4.9.0 is installed.
The sequence of events is the following:
1. A login page comes up that takes the username and password, and sends that
off to /LoginServlet to process. Note: I have also written and registered a Request Filter
for Tomcat that halts traversal beyone /lps-4.9.0 and checks for proper authentication
as I retrieve the cookies from requests trying to access those levels.
2. In the LoginServlet, I am creating a MACH COOKIE that I’ll send along with the response,
so that the Filter will allow me past the /lps-4.9.0 level. To do this I had to do a FORWARD
operation to preserve the cookie. a REDIRECT would just drop them. Since you can’t
give a relative path higher than the Servlet’s root, I had to turn on Tomcat’s “crossContext”
feature that allows me to do that in the same domain. And I have both contexts registered
in Tomcat’s conf directory in server.xml, I believe. Anyhow it works. I can grab the
/lps-4.9.0 context, get a Request Dispatcher, and then use that dispatcher to FORWARD
the request/response pair to my OpenLaszlo file(the LZX file).
So it seems to get as far as LOADING the OpenLaszlo page, but when I perused the console
messages in Chrome’s Developer Tools debugger, it showed that it was actually trying
to use the context of the original request(i.e. /LoginServlet); and of course that doesn’t
exist. I guess when I passed along the original request/response pair, the request had
the FIRST context used, and then tried to derive the relative path to the file off of that.
QUESTION: Can I just copy the stuff from the original request, but change the context,
and forward THAT?  Or architecturally should I try something else?
Thanks,
C
And the answer is..... You CAN'T DO IT... Period.
BTW. The Openlaszlo website server is DOWN, DEAD, KAPUT, NIX, GONE, NO MORE...
This will be the final project that I personally implement with the tool
with no support.
It's very sad to see something that had the right idea about development cycle times,
and keeping the client side GUI construction simple, fast, and easy could be something
that dies because of lack of interest? Say wha? Can't be because FLASH was in jeopardy.
I'm pretty sure that we, as programmers, aren't so paranoid about losing our jobs
that we think we must spend lots of hours CODING an interface to keep it secret.
I'm certainly not paranoid about it. I know there is NET BEANS for swing type
GUIS, and I've heard that GWT has adopted something similar now, and so I'll
keep looking for that perfect invention and deal with what is left over.
Critical Path must have been purchased by someone else too, and so the
site sponsor has no motivation to keep it alive, while it dies a slow death.

Surrender control from Pipeline to an HttpHandler

I have a problem with a website. The server is IIS 7, running ASP.NET on the .NET 4.0 CLR. We are hosting a Sitecore application and I hesitated in adding it as a tag, because I really feel it's more the 'why' of the question and not necessarily related to the underlying tech that's causing the problem.
One of the things Sitecore does is add a boatload of custom pipelines. One of these pipelines is called the LayoutResolverPipeline, which is responsible for determining the path to the layout file the requested page will use. We've come up with a terribly useful and complicated way of hosting global content items across multiple domains. Which domain will serve which items is completely configurable through the Administrator web GUI (aka the Sitecore shell). The end goal is to make it possible for our marketing/consumer experience team to run multivariate testing to find the best user experience.
To that end, we have a 'launch' page that is responsible for considering everything about the current user, everything about the current system and domain settings, and determines which experience to give the customer. For most domains, this comes down to a weighted roll of the dice - for the test results to be statistically sound, they have to be sufficiently random. It is written as an IHttpHandler and it stores its decisions in the HttpContext.Current.Session (which is accomplished by also having it implement the IRequiresSessionState interface). The decision is stored so that if the customer decides to backtrack, we don't roll the dice again and instead give them a consistent experience for the duration of their visit. The decision is carried out by the handler issuing a 302 redirect for the next page in the customer's visit.
The launch handler is defined in the web.config file in the usual way:
<system.webServer>
<handlers>
<add verb="*" path="launch.ashx"
type="CMS.HttpHandlers.LaunchRequestHandler, CMS"
name="LaunchHandler"/>
We occasionally do business with partners who, for whatever reason, don't want the resultant 302 between their page and ours. They will instead link directly to a certain customer experience. Over time, however, we depreciate, move or obsolete whole user experiences, which for certain demanding and lazy partners result in lingering links to unsupported or non-existent items. We also have to handle the case of people mis-typing, mis-remembering, mis-linking, revisiting from their browser history or just trying random urls.
These latter cases have resulted in some nasty exceptions in the LayoutResolverPipeline. I am trying to resolve these exceptions by having it fall back to the LaunchHandler if it can't figure out what to do. I have this implemented as a Redirect, but I would like to simply invoke the LaunchHandler directly; it is going to do a 301 to a different item, anyways, and having multiple redirects on a single request is a costly waste of resources that I would like to avoid.
Enough background. The problem is that LayoutResolverPipeline is bound to the HttpBeginRequest portion of the IIS processing stack, which is well before the Session information is ready. This is a constraint of Sitecore's and it can't be moved without solving a whole load of other problems.
Questions:
Is there a way to pass control to a specific IHttpHandler other than redirecting to the URL it is bound to?
Is there a way to rejoin the code a later point in the event pipeline? I suppose this would mean binding to the Application.PostAcquireRequestState event for a single request only, which sounds ludicrous.
Is there a way to acquire session state information early?
I'm of course open to suggestions for how I might be doing it completely wrong. Oh, and if you know of a more useful tag to throw on it for the Asp.net/IIS pipeline specifically, I wasn't able to find one that wasn't a read herring. Thanks!
I don't think you want to go manually invoking any handlers... that sounds pretty hacky. What about using Server.Transfer() here instead of a 301 Redirect? Then it's transparent on the user's end. Of course the disadvantage there is that it doesn't update the apparent URL, but you can't do that without some sort of redirect going on.

How to determine publishing user / access Engine in custom resolver

To enable custom user preferences during publishing we would like to find out in the resolve step (inside a custom resolver) what the publishing user is (so not the user account configured for the Publisher service but the user that initiated the publish operation).
To find the original publishing user we would need to have access to the PublishTransaction object (specifically the Creator property); we cannot use the User property from the Session inside the custom resolver as this Session is created by the Publisher service (and would give us the service account).
To find the current PublishTransaction Mihai has provided us with an excellent hack.
In essence; if we can get our hands on an Engine object we can determine the context publish transaction.
In our custom resolver the Resolve method is called with four parameters:
public void Resolve(
IdentifiableObject item,
ResolveInstruction instruction,
PublishContext context,
ISet<ResolvedItem> resolvedItems
) { }
The item can be used to provide us with a Session object but neither an IdentifiableObject nor a Session hold a reference to the Engine.
The resolve instruction is just a set of data properties for the resolve.
The publish context (unfortunately not a PublishingContext) holds the publication and publication target only.
A ResolvedItem can give us access to the Session again but not the Engine.
My question (finally) would be two-fold:
1. have I missed any potential points where the context user account can be determined from (other than the PublishTransaction)?
2. have I missed any potential points where the Engine can be determined from the parameters the IResolver.Resolve() method is being called with?
Edit: I realize I left out the broader picture on why we want to customize the publish activity with extra metadata (from user preferences) because it is a bit of a long story;
What I ultimately need is to activate for a specific version of a component in the component template (by walking up the version list and finding a version that is linked to a dedicated marker component) but in order to do that I need to know what the marker component is. For this reason we publish the marker component (which will resolve all linked components and ultimately pages) and the custom resolver allowed us to push the TCMURI of the marker component into the session cache (making it accessible in the CT).
Now we want to set a "preference" for a specific marker component at a user level to allow smaller batches of assets to be published within this marker context (as opposed to publishing everything linked to the marker at once).
Because the TBBs running inside the CT actually DO have an Engine object available, we can use Mihai's method and determine the publishing user (as opposed to pushing the marker context from the resolver what we initially did) and in this way bypass the issue completely.
I was wondering why there is such a difference in information availability between a resolve and a render operation; both are afterall part of the same publishing context. I cannot help but feel I'm overlooking something very basic but maybe I'm not and accessing a publishing context or engine from the resolver is simply impossible.
Edit: as presumed by Dominic and confirmed by Nuno there is no "Engine" at the time of resolving; as such this half of my question has been answered.
That leaves
have I missed any potential points where the context user account can be determined from (other than the PublishTransaction)?
I went down this road before in a project (trying to get the user in a Resolver extension) and it was a world of pain.
I moved from a Resolver extension to a Render Extension, and even considered a Transport extension, just to go back to the simplest approach possible: a TBB.
Granted, my use case was different than yours, as it looks like you may want to change the resolving behavior based on the user (some users don't like link propagation, right? - if they're afraid of changing content, then they shouldn't change it ;-) ) but I ended up not implementing it that way.
I think there was an Enhancement Request to include more info about the user triggering publishing actions, but if that is implemented in the product it will be for Tridion 2013, not sure you can wait that long.
I'd guess that you can't get your hands on an engine at this point. After all, you're resolving, not rendering. You mention that you want to "enable user preferences", but you don't tell us much more about your actual problem, rather than the line of investigation you are currently following (which may or may not be a dead end).
What kind of user preferences are relevant to publishing, and why do you need to have them in the resolver?

Adding information to transport package manifest (instructions.xml) when unpublishing any item?

I have a use case where I need to add information about the user that created the current publish transaction (more than just their user name, I also need group memberships and some other details) and pass it on to a deployer extension.
When publishing this is relatively easy to do with the following code
engine.PublishingContext.RenderedItem.AddInstruction(
InstructionScope.Global, instruction);
As you may notice this method "AddInstruction" is only available for a "RenderedItem", but Unpublish instructions do not render items, and therefore I cannot use the same technique.
Short of hacking the package manifest in the file system when generating it (for instance in a custom resolver) how would you tackle this requirement?
Do you have more info on what you need to do with this information in the Deployer. Would it be an option to capture the un-publish action after it happens with an event handler, and then create a second publish action which sends the message to the Deployer with the additional information? (I know that means 2 round trips, but I can't think of another approach at this point). Un-publish actions have been a bit tricky ever since R4, back in R3 we actually had code which was executed by templates in the unpublish phase (although it was all Perl back then).
I wonder whether this is a missing extensibility point. After all, I can see why you would want to transmit extra data with an unpublish. So firstly, I'd suggest an enhancement request to have some functionality added to support this use case.
Getting to the point of your question... how to implement something without hacking the package. Perhaps you could make the information available through another mechanism. For example, you could write a web service that runs on the content manager and which serves the data when queried for a given publish transaction ID.

long running http process - how to put in separate process?

I know that similar questions have been asked all over the place, but I'm having trouble finding one that relates directly to what I'm after.
I have a website where a user uploads a data file, then that file is transformed and imported into SQL. The file could be up to 50mb in size, and some times this process can take 30 minutes or sometimes even longer.
I realise I need to palm off the actual work to another process, and poll that process on the web page. I'm wondering what the best approach would be though? Being a web developer by trade, I'm finding all this new Windows Service stuff a bit confusing, and I just wanted somewhere to start.
So:
Can I do / should I being doing this with a windows service? if so, how?
Should I use WCF? If this runs under IIS, will I have problems with aspnet_wp.exe recycling and timing out my process?
clarifications
The data is imported into sql, there's no file distribution taking place.
If there is a failure, it absolutely MUST be reported to the user. The web page will poll every, lets say, 5 seconds, from the time the async task begins, to get the 'status' of the import. Once it's finished another response will tell the page to stop polling for status updates.
queries on final decision
ok, so as I thought, it seems that a windows service is the best idea. So as to HOW to get it to work, it seems the 'put the file there and wait for the service to pick it up' idea is the generally accepted way, is there a way I can start a process run by the service, without it having to constantly be checking a database table / folder? As I said earlier, I don't have any experience with Windows Services - I wondered if I put a public method in the service, can I call it somehow?
well ...
var thread = new Thread(() => {
// your action
});
thread.Start();
but you will have problems with that:
what if the import to sql fails? should there be any response to the client
if it fails, how do you ensure the file on a later request
what if the applications shuts down ... this newly created and started thread will be killed either
...
it's not always a good idea to store everything in sql (especially files...). if you want to make the file available to several servers why not distribute them via ftp ...?
i believe that your whole concept is a bit messed up (sry assuming this), and it might be helpful if you elaborate and give us more information about your intentions!
edit:
Can I do / should I being doing this
with a windows service? if so, how?
you can :) i advise you to create a simple console-program and convert this with srvany and sc. you can get a rough overview howto here (note: insert blanks after =... that's a silly pitfall)
the term should is relative, because you did not answer the most important question
what if a record is persisted to the database, telling a consumer that file test.img should be persisted, but your service hasn't captured it or did not transform it yet?
so ... next on
Should I use WCF? If this runs under IIS, will I have problems with aspnet_wp.exe recycling and timing out my process?
you probably could create a WCF-service which recieves some binary-data and then stores this to a database. this request could be async. yes. but what for?
once again:
please give us more insight to your workflow: what are you exactly trying to achieve? which "environmental-conditions" to you have (eg. app A polls db and expects file-records which are referenced in table x to be persisted) ...
edit:
so you want to import a .csv-file. well that changes everything :)
but i won't advise you to use a wcf-service (there could be a usage: eg. a wcf-service which has a method to insert a single row, then your iteration through the file would be implemented in another app... not that good, though).
i would suggest following:
at first do everything in your webapp (as you've already done), but rather use some sort of bulk-insert and do your transformation/logic on the database.
if you have some sort of bottle-neck then, i would suggest you something like a minor job-service, eg:
webapp will upload the file and insert a row to a job-table. the job-service is continiously polling the table/or gets informed via wcf by the webapp (hey, hey, finally some sort of usage for WCF in your scenario... :) ) and then does the import-job, writing a finish-note to a table/or set the state of the job to finished ...
but this is a bit overkill :)
Please see if my below comments helps you to resolve your issue:
•Can I do / should I being doing this with a windows service? if so, how?
Yes you can do this with a windows service. And I think that is the way you should be doing it. You can implement your own service to process your request or you can use the open source code Job Proccessor
Basically the idea is..
You submit a request for processing
the csv file in database table with
some status as not started.
Then your windows service picks up
the request from database table which
are not started and update them as in
progress status.
Once the processing is complete
succesfully /unsuccesfuly your
service updated the database table
with status as Completed / Failed.
And your asp.net page can poll to
database table for the current status
every 5 sec or so.
•Should I use WCF? If this runs under IIS, will I have problems with aspnet_wp.exe recycling and timing out my process?
you should not be using WCF for this purpose.

Resources