Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDEV-4818 add sessionCommit() function #2496

Open
wants to merge 3 commits into
base: 6.2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion core/src/main/java/lucee/runtime/PageContextImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,8 @@ private boolean lastStanding() {
while ((p = p.getParentPageContext()) != null) {
if (p.getStartTime() > 0) return false;
}

if (getParentPageContext() == null
&& (tmp != null && tmp.size() == 0 )) return true; // TODO nested children?
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package lucee.runtime.functions.system;

import lucee.runtime.PageContext;
import lucee.runtime.PageContextImpl;
import lucee.runtime.exp.PageException;
import lucee.runtime.ext.function.Function;

public class SessionCommit implements Function {
private static final long serialVersionUID = -2243745577257724777L;

public static String call(PageContext pc) throws PageException {
((PageContextImpl) pc).sessionScope().touchAfterRequest(pc);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public IKStorageValue loadData(PageContext pc, String appName, String name, Stri
Object val = cache.getValue(key, null);
if (val instanceof byte[][]) {
ScopeContext.info(log,
"load existing data from cache [" + name + "] to create " + strType + " scope for " + pc.getApplicationContext().getName() + "/" + pc.getCFID());
"Load existing byte data from cache [" + name + "] to create " + strType + " scope for " + pc.getApplicationContext().getName() + "/" + pc.getCFID());
return new IKStorageValue((byte[][]) val);
}
else if (val instanceof IKStorageValue) {
ScopeContext.info(log,
"load existing data from cache [" + name + "] to create " + strType + " scope for " + pc.getApplicationContext().getName() + "/" + pc.getCFID());
"Load existing data from cache [" + name + "] to create " + strType + " scope for " + pc.getApplicationContext().getName() + "/" + pc.getCFID());
return (IKStorageValue) val;
}
else {
ScopeContext.info(log, "create new " + strType + " scope for " + pc.getApplicationContext().getName() + "/" + pc.getCFID() + " in cache [" + name + "]");
ScopeContext.info(log, "Create new [" + strType + "] scope for [" + pc.getApplicationContext().getName() + "/" + pc.getCFID() + "] in cache [" + name + "]");
}
return null;
}
Expand All @@ -70,6 +70,7 @@ else if (existingVal != null) {
cache.remove(key);
}
}
ScopeContext.info(log, "Store scope for [" + pc.getApplicationContext().getName() + "/" + pc.getCFID() + "] in cache [" + name + "]");
}
catch (Exception e) {
ScopeContext.error(log, e);
Expand Down
11 changes: 10 additions & 1 deletion core/src/main/java/resource/fld/core-base.fld
Original file line number Diff line number Diff line change
Expand Up @@ -12646,7 +12646,16 @@ You can find a list of all available timezones in the Lucee administrator (Setti
<type>string</type>
</return>
</function>


<!-- SessionCommit -->
<function>
<name>SessionCommit</name>
<class>lucee.runtime.functions.system.SessionCommit</class>
<description>Force saving the session to storage, useful when sessionCluster is enabled.</description>
<return>
<type>void</type>
</return>
</function>

<!-- SessionStartTime -->
<function>
Expand Down
39 changes: 29 additions & 10 deletions test/tickets/LDEV2135.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="session" {

function run( testResults , testBox ) {
describe( "Test suite for LDEV-2135 using memory", function() {

//beforeEach(function (currentSpec, data){ _beforeEach(currentSpec, data); });

it( title='thread looses session variables - sessionCluster=false', body=function( currentSpec ) {
test( {sessionCluster: false, sessionStorage: "memory"} );
});
Expand All @@ -12,41 +15,52 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="session" {
});

describe( title="Test suite for LDEV-2135 using redis", skip=skipRedis(), body=function() {

//beforeEach(function (currentSpec, data){ _beforeEach(currentSpec, data); });

it( title='thread looses session variables - redis- sessionCluster=false', body=function( currentSpec ) {
test( {sessionCluster: false, sessionStorage: "redis"} );
});

it( title='thread looses session variables - redis - sessionCluster=true', skip=true, body=function( currentSpec ) {
it( title='thread looses session variables - redis - sessionCluster=true', body=function( currentSpec ) {
test( {sessionCluster: true, sessionStorage: "redis"} );
});

it( title='thread looses session topLevel variables - redis - sessionCluster=true', body=function( currentSpec ) {
test( {sessionCluster: true, sessionStorage: "redis"}, "TopLevel" );
});
});

describe( title="Test suite for LDEV-2135 using memcached", skip=skipMemcached(), body=function() {

//beforeEach(function (currentSpec, data){ _beforeEach(currentSpec, data); });

it( title='thread looses session variables - memcached -sessionCluster=false', body=function( currentSpec ) {
test( {sessionCluster: false, sessionStorage: "memcached"} );
});

it( title='thread looses session variables - memcached -sessionCluster=true', skip=true, body=function( currentSpec ) {
it( title='thread looses session variables - memcached -sessionCluster=true', body=function( currentSpec ) {
test( {sessionCluster: true, sessionStorage: "memcached"} );
});
});
}

private function test( args ){
private function test( args, string template="" ){
var uri = createURI( "LDEV2135" );
var first = _InternalRequest(
template : "#uri#/cfml-session/testThreadSession.cfm",
template : "#uri#/cfml-session/testThreadSession#template#.cfm",
url: args
);
systemOutput(args, true);
checkSess( first.fileContent );

var cookies = {
cfid: first.session.cfid,
cftoken: first.session.cftoken
};

systemOutput("-- before secondRequest.cfm", true);
var second = _InternalRequest(
template : "#uri#/cfml-session/secondRequest.cfm",
template : "#uri#/cfml-session/secondRequest#template#.cfm",
url: args,
cookies: cookies
);
Expand All @@ -63,10 +77,10 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="session" {
expect( s.threads ).toHaveLength( 5 );
expect( s ).toHaveKey( "afterJoin" );
}

private string function createURI(string calledName){
var baseURI = "/test/#listLast(getDirectoryFromPath(getCurrentTemplatePath()),"\/")#/";
return baseURI&""&calledName;
private string function createURI(string calledName, boolean contract=true){
var base = getDirectoryFromPath( getCurrentTemplatePath() );
var baseURI = contract ? contractPath( base ) : "/test/#listLast(base,"\/")#";
return baseURI & "/" & calledName;
}

private function skipRedis(){
Expand All @@ -76,4 +90,9 @@ component extends="org.lucee.cfml.test.LuceeTestCase" labels="session" {
private function skipMemcached(){
return (structCount(server.getTestService( "memcached" )) eq 0);
}

private function _beforeEach(currentSpec, data){
systemOutput("", true);
systemOutput(currentspec, true);
}
}
6 changes: 5 additions & 1 deletion test/tickets/LDEV2135/cfml-session/secondRequest.cfm
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<cfscript>
//systemOutput(session.toJson(), true);
if (!structKeyExists(session, "ldev3125")){
//systemOutput(session.toJson(), true);
throw "key session.ldev3125 missing";
}
//systemOutput(session.ldev3125.toJson(), true);
echo(session.ldev3125.toJson());
</cfscript>
3 changes: 3 additions & 0 deletions test/tickets/LDEV2135/cfml-session/secondRequestTopLevel.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<cfscript>
echo(session.toJson());
</cfscript>
10 changes: 7 additions & 3 deletions test/tickets/LDEV2135/cfml-session/testThreadSession.cfm
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<cfscript>
//systemOutput(url.toJson(), true);
session.ldev3125 = {};
session.ldev3125.sessionCluster = url.sessionCluster;
session.ldev3125.start = 'survived';
Expand All @@ -13,15 +14,18 @@
thread name="#name#" {
try {
ArrayAppend( session.ldev3125.threads, thread.name );
sleep( 10 );
// sleep( 10 ); // might need to be 1000
throw(type="blah", message="boom");
} catch(any e) {
writedump(session.ldev3125);
dump(session.ldev3125);
}
}
}

session.ldev3125.beforeJoin = 'hello';
thread action="join" name="#_threads.toList()#";
session.ldev3125.afterJoin = 'goodbye';
echo( session.ldev3125.toJson() );
//systemOutput(session.toJson(), true);
//session.topLevel = true;
//sessionCommit();
</cfscript>
30 changes: 30 additions & 0 deletions test/tickets/LDEV2135/cfml-session/testThreadSessionTopLevel.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<cfscript>
//systemOutput(url.toJson(), true);
session.sessionCluster = url.sessionCluster;
session.start = 'survived';
session.threads = [];
session.sessionStorage = url.sessionStorage;

_threads = [];

for(i in [ 1, 2, 3, 4, 5 ] ) {
name = "ldev2135-#i#";
arrayAppend( _threads, name);
thread name="#name#" {
try {
ArrayAppend( session.threads, thread.name );
// sleep( 10 ); // might need to be 1000
throw(type="blah", message="boom");
} catch(any e) {
dump(session);
}
}
}
session.beforeJoin = 'hello';
thread action="join" name="#_threads.toList()#";
session.afterJoin = 'goodbye';
echo( session.toJson() );
//systemOutput(session.toJson(), true);
session.topLevel = true;
//sessionCommit();
</cfscript>
Loading