User:Void Singer/Saucer
Saucer
What is it?
Saucer is an optional open source Extension to Teacup that helps prevent missing or bad pages from delaying webpage loads.
How does it work?
Once Saucer starts up, it advertises it's existence to available file sources, which can signal which pages they have available to serve. If it hears a request from the Teacup server, it checks to see if the requested page is already known to it, and if so, does nothing. If not, the page name is added to a queue and then Saucer waits a few seconds to see if anything responds to that request; if not, it sends a "404 Not Found" message to the server so that webpages waiting for it can know that the file isn't available and continue immediately. If a service does respond to the request within 2 seconds, with a "100 Continue", Saucer will not send a 404 message for that request. Additionally, any request that is filled via a "200 Success" message, will be added to it's list of known files.
Code
Saucer
/*( Saucer v0.5 )*/
/*//-- Request Handler variables --//*/
list gLstPag; //-- List of known pages
list gLst404Tim; //-- 404 timeout
list gLst404Key; //-- 404 request key
list gLst404Pag; //-- 404 page name (used for discovery only)
integer gIntLnk; //-- link number to save on function calls
default{
state_entry(){
gIntLnk = llGetLinkNumber();
llMessageLinked( LINK_SET, 418, "Saucer Start", NULL_KEY );
}
link_message( integer vIntSrc, integer vIntDta, string vStrDta, key vKeyDta ){
if (vKeyDta){ //-- server traffic?
if (418 == vIntDta && gIntLnk == vIntSrc){ //-- server request? // next line: Ignore Known Pages
if (!~vIntDta = llListFindList( gLstPag, [vStrDta = llList2String( llParseStringKeepNulls( vStrDta, ["?"], [] ), 0 )] )){
gLst404Key += [vKeyDta]; //-- Pending 404 key (used to detect lazy page additions or Send 404s)
gLst404Pag += [vStrDta]; //-- Pending 404 name (used for lazy Know Page additions)
gLst404Tim += [llGetUnixTime() + 2]; //-- Timeout value: this actually amount to a ~2.25sec timeout
if (gLst404Tim == [""]){ //-- Only start timer for first pending 404, avoids bumping the timer forward.
llSetTimerEvent( 0.75 ); //-- Fast to deal with fast pages requests
}
} //-- Next Line: Check for unadvertised responses for pending 404s
}else if (~vIntSrc = llListFindList( gLst404Key, [vKeyDta] )){
if (200 == vIntDta){ //-- auto discovery of unadvertised pages
gLstPag += [llList2String( gLst404Pag, vIntSrc )];
}
gLst404Tim = llDeleteSubList( gLst404Tim, vIntSrc, vIntSrc );
gLst404Key = llDeleteSubList( gLst404Key, vIntSrc, vIntSrc );
gLst404Pag = llDeleteSubList( gLst404Pag, vIntSrc, vIntSrc );
}
}else if (601 == (1 | vIntDta) && NULL_KEY == (string)vKeyDta){
if (1 & vIntDta){ //-- 601 = add file (if NOT found)
if (!~vIntDta = llListFindList( gLstPag, [vStrDta] )){
gLstPag += [vStrDta];
}
}else{ //-- 600 remove file (only if found, avoids wrong index)
if (~vIntDta = llListFindList( gLstPag, [vStrDta] )){
gLstPag = llDeleteSubList( gLstPag, vIntDta, vIntDta );
}
}
}
}
timer(){ //-- handle pending 404s
if (gLst404Tim != []){ //-- Pending 404s?
while (llList2Integer( gLst404Tim, 0 ) < llGetUnixTime()){ //-- Timeouts expired?
llMessageLinked( llGetLinkNumber(), 404, "404 Not Found", llList2Key( gLst404Key, 0 ) );
gLst404Tim = llDeleteSubList( gLst404Tim, 0, 0 ); //-- Send 404, Remove pending
gLst404Key = llDeleteSubList( gLst404Key, 0, 0 );
gLst404Pag = llDeleteSubList( gLst404Pag, 0, 0 );
if (gLst404Tim == []){ //-- Pending Queue empty?
llSetTimerEvent( 0.0 );
return; //-- Stop timer, & exit
}
}
}else{ //-- No Pending 404s, stop timer
llSetTimerEvent( 0.0 );
}
}
}
/*//-- License Text --//*/
/*// Free to copy, use, modify, distribute, or sell, with attribution. //*/
/*// (C)2011 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ] //*/
/*// Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ] //*/
/*// All usages must contain a plain text copy of the previous 2 lines. //*/
/*//-- --//*/
Protocol
Special Messages
Saucer accepts three special messages using the Teacup Protocols.
- "File Removed"
llMessageLinked( LINK_SET, 600, "File Name", NULL_KEY ); //-- as called by another script
- "File Added"
llMessageLinked( LINK_SET, 601, "File Name", NULL_KEY ); //-- as called by another script
- "100 Continue"
llMessageLinked( LINK_SET, 100, "File Name", REQUEST_KEY ); //-- as called by another script
where "File Name" is the name of the file that the service is adding, removing, or serving. and REQUEST_KEY is the key of the request from the server for that file.
- LINK_SET should be replaced with the server prim number when known to prevent spamming messages
Basic Functions
Upon startup, Saucer will advertise it's availability with "Saucer Start"
Services that take longer than 2 seconds to respond normally have two options to avoid their pages being timed out quickly
- Send a "File Added" message for each file name they service when they start, and when they receive the "Saucer Start" advertisement
- File names added in this manner should be removed with "File Removed" when no longer available
- "File Added" messages should be throttled to no more than a few per second, suggest adding a delay based on link number.
- Immediately send a "100 Continue" message for server requested file names, then send the requested file normally when available.
- This method does not require removal unless sent with a "200 Success" code. Instead, use codes "201 Created", "202 Accepted", or "204 No Content"
other services that can respond quickly should send files with "200 Success" where applicable to prevent additional processing by Saucer. Otherwise they should use Option 1 above.
- Any file sent with a "200 Success" code will be added to the known files list
Notes
Compatible Servers, File Systems, and Extensions
- Teacup - SIP front end
- Red Tea - A very simple SIP back end File Service for a starting point.
- Region Stats - A single page Extension that gets live data from the region and refreshes every minute
- Tea Strainer - Optional Troubleshooting Monitor for checking messages being sent and received.
Known Bugs
- Current version responds to any unknown code in the proper format as if it were a "100 Continue".
- This may be cleaned up in a future revision, Do not rely on this behavior
- Not really a bug, but inefficient... must have one copy for each server
- probably needs revised to save the server source too so that it can handle multiple Teacups
Requested Feature Upgrades
- Got a feature request? add it here
Change Log / Old Versions
Most Recent Changes are at the top, old version links below.
- Code will be considered stable when it reaches v1.0
- Saucer v0.5
- Update to match version number on Teacup, transparent tweaks and page formatting.
- Saucer v0.3.1
- Separated from The Teacup Server, and Messaging Protocol tweaked
- Saucer v0.3
- Initial Public Release