I recently purchased Web Connection and am trying to build an eCommerce site with it. The site will use a REST protocol and jQuery Mobile on the client. This will be a very high transaction rate ticketing site. One of my bigger challenges is creating reusable objects. For instance, I'm building a class that handles Authorize.net charge requests. I would like a pool of instances to stay memory resident for efficiency. My question is: How do I achieve this with Web Connection? Also, do the objects need to function in a stateless manner because I'll never know which instance I'm using between calls?
Is there a certain class (e.g. wwRestService) that I must subclass to get reusable functionality? Should I be using wwwebserver and it's cApplicationPool property? Are there any examples of this?
Can someone shed light on this subject? I tried searching for "Web Connection" plus "reuse" or "reusability" in the documentation and on the web...nothing.
Depends on what you need to do.
I've added a blog post
There's no 'stickyness' to Web Connection instances unless you use some sort of load balancing front end to it, which means each instance gets it's own address space and so you can only cache things per Web Connection EXE 'instance'.
Any class you hang off of the wwServer instance (ie. wcDemoServer, MyAppServer etc.) will be essentially application static and live throughout the life time of the application. There are a few ways to do this all involving objects hung off the wwServer instance.
Create your own 'Manager' object that hosts anything you want to cache - you create a class and add any sub objects/values on it that you essentially want to cache for the duration of the app:
DEFINE CLASS MyAppServer as wwServer oStatics = null FUNCTION Init() this.oStatics = CREATEOBJECT("MyCacheObjectContainer") this.oStatics.oAuthorizeNet = CREATEOBJECT("AuthorizeNetProcessor") this.oStatics.oImageProcess = CREATEOBJECT("ImageProcessor")
Then in the app in a request anywhere:
loAuthNet = Server.oStatics.oAuthorizeNet loCardResult = loAuthNet.Process(loCardInfo)
Another option is the wwServer::oResources collection that you can use to store arbitrary objects to.FUNCTION Init()
loAuthNet = Server.oResources.oAuthorizeNet loCardResult = loAuthNet.Process(loCardInfo)
FWIW, I don't think there's much benefit for caching things like Authnet objects since that basically makes throwaway HTTP connections which is very fast. The only things you want to cache are things that require long winded configuration or preloading of data that you don't want to do for every hit.
+++ Rick ---
Thanks Rick; your blog post is just the info I was looking for. Also, in this article: https://weblog.west-wind.com/posts/2005/Feb/12/Comparing-West-Wind-Web-Connection-and-classic-ASP-COM, you refer to a Pool Manager for server instances. I assume that's a Pool Manager that you wrote, not the IIS Application Pool. Where is the number of instances configured? You also state that long running processes can be delegated outside the pool of servers. Can you provide an example of how that is done?
Yes I prefer running a fixed set of servers because you can control the number of instances and as described in yesterday's post - you can cache resources which overall leads to better performance of actual FoxPro processing as state doesn't have to be spun up every time a server instance is loaded.
The documentation has lots of references to this. Here's is one (old but still as relevant as it's always been):
The biggest issue you have to wrestle with FoxPro and Web Connection is slow requests tying up server instances. If requests are fast you can great throughput (I regularily hit 150+ req/sec for optimal scenarios in local testing). But slow requests that tie up the pool (ie. outrun available instances) need to be offloaded to some sort of async processing mechanism.
+++ Rick ---
In this article: https://weblog.west-wind.com/posts/2005/Feb/12/Comparing-West-Wind-Web-Connection-and-classic-ASP-COM, you refer to a COM Pool Manager for server instances. You state, "there’s a manager object presiding over the actual COM invocation calls that monitors the operation of the Web -> VFP interface and can detect many abnormalities." Which object is this? Where are the number of instances and timeout configured?
You also state that long running processes can be delegated outside the pool of servers. Can you provide an example of how that is done?
The pool manager is internal in the .NET and ISAPI modules. You can configure either through their configuration files:
wc.ini respectively. You basically configure the number of instances that you want to run.
There are some old white papers you can search for for async operations. Other than that there's no real guidance here because typically running long running requests means offloading to another server or some backend process/service that handles the operations and then calls back.
Back in those days http refresh headers were used but today you'd use Ajax calls or Web Sockets to handle the long running requests. You can hook into SignalR on .NET from FoxPro which can make two-way push operations with events quite effective including browser notifications. I'll have a session on this topic at Southwest Fox later this year.
There's also this:
which allows you to spin up additional instances for longer running proccesses that run outside of the regular pool.
+++ Rick ---