Formiko
08/21/2022, 1:59 AMrodyon
09/10/2022, 4:29 PMScott Conklin
09/16/2022, 2:46 PMScott Conklin
09/16/2022, 2:49 PMrc["response"]["errors"] = 'Sorry, something went wrong';
variables.fw.renderData().type( 'json' ).data( rc.response ).statusCode( 200 ).statusText( "Successful" );
return;
Formiko
09/20/2022, 7:40 PMFormiko
09/21/2022, 12:46 AMFormiko
09/21/2022, 12:47 AMFormiko
09/21/2022, 1:10 AMrodyon
09/21/2022, 12:27 PMFormiko
09/21/2022, 1:43 PMFormiko
09/21/2022, 1:51 PMGVJustDOIT
09/27/2022, 7:03 PMScott Conklin
09/28/2022, 11:42 PMproperty config;
...
public void function setupApplication() {
settings = config.getSettings();
application.AESKey = settings.keys.AES ;
application.captchaKey = settings.keys.captcha;
application.VTID = settings.application.vtid;
application.COTID = settings.application.cotid;
application.securelist = settings.securelist;
application.env = getEnvironment();
}
Charles Robertson
11/02/2022, 9:17 AMfunction list(rc){
rc.page = 1;
variables.blogService.page(rc.page);
rc.data = variables.blogService.list();
}
blogService
component accessors = true{
variables.blogs = {};
// constructor etc…
function page(page){
// build variables.blogs struct from DB query
}
function list(){
return variables.blogs;
}
}
So, essentially, the blogService
page method uses a DB query to populate:
variables.blogs
And then I immediately return this variable, in the list()
method.
What worries me, is that if there are two different requests like:
REQUEST 1:
rc.page = 1;
variables.blogService.page(rc.page);
rc.data = variables.blogService.list();
REQUEST 2:
rc.page = 2;
variables.blogService.page(rc.page);
rc.data = variables.blogService.list();
The list data might get mixed up?
My question:
Are the two method calls, atomic, in the blogController
, per request?
I know that Coldfusion is multi-threaded, so requests are dealth with, in parallel.
I am worried that the following might happen:
REQUEST 1 rc.page = 1;
REQUEST 1 variables.blogService.page(rc.page);
REQUEST 2 rc.page = 2;
REQUEST 2 variables.blogService.page(rc.page);
REQUEST 1 rc.data = variables.blogService.list();
REQUEST 2 rc.data = variables.blogService.list();
Essentially, the user responsible for REQUEST 1 will receive the REQUEST 2 data.
I feel that data is safe, within a singleton, as long as methods are UDFs [functional/stateless methods], but when there is stateful data, in a singleton, then the alarm bells start ringing.
I am not sure why I decided to create a component variables variable, but I think I found it in an FW1 example.
The three potential solutions I have, are:
1) Make services instances, not singletons [remove from the application scope] CANNOT DO THIS AS FW1 THROWS AN ERROR
2) Lock the two method calls, like:
cflock (name="listBlogService", type="exclusive", timeout="30") {
variables.blogService.page(rc.page);
rc.data = variables.blogService.list();
}
3) Remove the blogService
list()
method and return the list from the page()
method. This would turn the page()
method into a UDF, removing references to state.
I am veering towards option 3?rodyon
11/02/2022, 10:32 AMREQUEST 1 rc.data = variables.blogService.list();
REQUEST 2 rc.data = variables.blogService.list();
I think if something like this happen in Lucee/Coldfusion, it would be abandoned somewhere around year 2000 as unusable platform. I'm not big on multithreading, but never got an issue you mentioned with cfml or fw/1 in years.Charles Robertson
11/02/2022, 11:30 AM<http://variables.blog|variables.blog>
, I am not so sure.
I mean, we are sometimes meant to lock down application variables and other bits of code that might spawn a race condition.
I just wondered whether this is one such example?rodyon
11/02/2022, 1:11 PMwebsolete
11/02/2022, 1:18 PMwebsolete
11/02/2022, 1:19 PMJim Priest
11/02/2022, 1:22 PMrodyon
11/02/2022, 1:36 PMCharles Robertson
11/02/2022, 1:57 PMproperty fooService;
My understanding is that because the actual controller component is in the application scope, everything inside the component, including properties, which are in the variables
scope, also persist.
You can see this when you dump out the application scope.
The point I am trying to make, is that any variable inside a service, in the variables
scope, is a singleton, as well.
This makes it vulnerable to being changed by more than one request.
If services were transients, each request would get given a new instance. In this case, there would be no problem, because each request would be given its own copy of all the variables inside each service.Charles Robertson
11/02/2022, 2:03 PMwebsolete
11/02/2022, 2:30 PMCharles Robertson
11/02/2022, 3:17 PMvariables
scope mutation inside a singleton.
I only used this approach, because I found it in an FW1 example application. And to be fair, the objective, within the example app, was very possibly correct and I corrupted it.
So, I’m going to remove the variables
scope variable and just return the list data from the page()
method.
Before:
function page(page){
// build variables.blogs struct from DB query
…
cfloop(query=local.qGetFile, startrow=local.startrow, endrow=local.endrow){
// add blog bean to variables.blogs
…
variables.blogs[local.qGetFile.File_ID] = blog;
}
}
After:
function page(page){
// build variables.blogs struct from DB query
…
local.pagedata = {
recordcount: local.recordcount,
list: {}
};
cfloop(query=local.qGetFile, startrow=local.startrow, endrow=local.endrow){
// add blog bean to variables.blogs
…
local.pagedata.list[local.qGetFile.File_ID] = blog;
}
return local.pagedata;
}
seancorfield
11/02/2022, 5:35 PMrc
or `local`/`var` scope variables only. The variables
scope of a controller should only be used to cache global state (like an in-memory copy of a fixed lookup table or some such) and should either be initialized in the constructor method init()
via dependency injection, or with careful locking as if dealing with application
scope.dfgrumpy
12/28/2022, 4:47 PMtmcneer
01/31/2023, 4:52 PMrodyon
02/03/2023, 5:29 PMjakobward
02/23/2023, 1:04 AMjakobward
02/23/2023, 1:04 AM