I built a Varnish VMOD that defines an object, which is instantiated in vcl_init and is always kept in memory, and used in individual requests.
My configuration is split up in several VCL files, that get loaded from a "master" VCL depending on some request parameters.
The master VCL also instantiates the object in question, which I want to use in another VCL. The reason why I don't instantiate the object in the same VCL I use it in, is that I have another VCL that defines some ACL-restricted routes to update the object from a data source.
E.g. master.vcl:
sub vcl_init {
new myobj = mymodule.myobject();
}
sub vcl_recv {
if (req.url ~ "^pub/") {
return (vcl (pub_vcl));
}
// Other switches...
}
pub.vcl:
sub vcl_recv {
if myobj.mymethod() {
set req.http.x-bogus = "true";
}
}
But in this case, compilation fails because myobj is undefined in pub.vcl, which means it does not carry from master.vcl.
I also thought about adding the test and header setting in master.vcl before loading pub.vcl, but that won't work because loading a VCL calls std.rollback(req) which unsets all the request headers, which is the only variable accessible in vcl_recv.
Is there a way to pass this state across VCL reloads?
Thanks.
You can't do this with objects directly as they are scoped by the VCL and can't "escape" it. As you've experienced, you need to load the labeled vcl first, so you also need to create the object in it.
But nothing prevents you from creating objects that reference a global variable so all objects have access to the same data.
Alternatively, you can use the Event function to use a PRIV_VCL (https://stackoverflow.com/a/60753085) also referencing a global pointer and avoid using objects completely. This is what is done here for example: https://github.com/varnish/varnish-modules/blob/master/src/vmod_vsthrottle.c#L345
Related
I have repetitive code in my vcl and I want to create custom function without embedding inline C code. Is it possible?
You can define a custom subroutine like this
sub my_subroutine {
...
}
and call it like this:
call my_subroutine;
From: http://book.varnish-software.com/4.0/chapters/VCL_Basics.html
Subroutines in VCL take neither arguments nor return values. Each
subroutine terminates by calling return (action), where action is a
keyword that indicates the desired outcome. Subroutines may inspect
and manipulate HTTP header fields and various other aspects of each
request. Subroutines instruct how requests are handled.
Subroutine example:
sub pipe_if_local { if (client.ip ~ local) {
return (pipe); } }
To call a subroutine, use the call keyword followed by the
subroutine’s name:
call pipe_if_local;
Varnish has built-in subroutines that are hook into the Varnish
workflow. These built-in subroutines are all named vcl_*. Your own
subroutines cannot start their name with vcl_.
Is it a best practice to wrap the ServiceStack's JsonServiceClient within a using statement?
var client = new JsonServiceClient();
client.Post(request);
versus
using (var client = new JsonServiceClient())
{
client.Post(request);
}
Which one is the best?
JsonServiceClient implements IDisposable so best practise would be to use it with a using statement.
However there are scenarios whereby you need to the share an instance of the JsonServiceClient across multiple requests (Such as when you use cookie based sessions, as the cookies are contained in the instances cookie container), in which case you would use the client without a using statement, but ensure that your application calls the Dispose method of the client, when it no longer requires the client.
This answer by gdoron further explains the best practise regarding classes that implement IDisposable such as the JsonServiceClient and the reasoning behind it.
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
I hope that helps.
I might be on the wrong track here, but here goes:
In my PhoneGap Durandal app, I have a Profile View/VM which only returns data the first time it is hit - after that it checks a bool called initialised and wont hit the DB again the 2nd time. This works fine.
However after Logout, I need to invalidate the cache. I could use a message to tell the Profile VM to clear the variable (ie. invalidate the cache) but I thought perhaps there is a higher-level way of doing this in Durandal - e.g. On Logout, I tell dispose of all ViewModels in memory (there may be other Singleton objects with session specific info in them).
Advice please...
This is more of a javascript question and this is just my understanding of how javascript works.
Javascript will automatically dispose of objects that are no longer referenced through a mechanism called Garbage Collection.
Here is a good article on how Garbage Collection works. Basically it will dispose of objects that are no longer referenced in your program.
There is another method in javascript that allows you to remove objects. The delete method:
delete someobj;
Which too my knowledge is pretty much equal to someobj = undefined;
Hope this helps.
***Edit
Durandal follows the screen activator pattern for it's viewmodels. So apart of the viewmodel lifecycle it will call an activate, candeactivate, and deactivate method.
You could do your disposing in the deactivate method.
(Durandal 2.0) You could always hook into the composition life-cycle callback methods on your view-model. There are four: activate(), attached(), deactivate(), and detached(). They are called automatically by Durandal on your view-model, if they exist. In my projects, if I need a view to invalidate its cache, I hook into the deactivate() method and put the cleanup logic there. Similarly, I use the detached() method to unbind events and destroy UI widgets.
Simple example:
define(['modules/myDataService'],
function(dataservice) {
var cache;
function activate() {
return dataservice.getData().done(function(response) {
cache = response;
});
}
function deactivate() {
cache = null;
}
return {
activate: activate,
deactivate: deactivate
};
});
Source documentation: http://durandaljs.com/documentation/Hooking-Lifecycle-Callbacks/
I had declared and used a global variable in ssjs library as below:
var backendDoc:NotesDocument = null;
function savedata () {
print (backendDoc.getItemValueString("fieldname")); // crash here
}
I assigned a document object to it in the Edit button just after changing docuemnt mode from read to edit:
backendDoc = document1.getDocument(); // get backend document from datasource called document1
The code in above function return error NotesDocument.getItemValueString("string")) null. Apparently, the backendDoc is null.
Any ideas how to assign value and use global variable in ssjs library? Thanks in advance
There are 2 problems with your code:
as Michael pointed out: you should use a scoped variable. Global variables in script libraries are actually application global (think applicationScope) and might be unloaded any time if memory gets tight (behavior of them depends on the XPages version)
You can't use NotesObjects here. Between the calls the C Object that backs the JS object is released and your object becomes invalid.
You can either store the NoteId in a scoped variable and retrieve the NotesDocument every time or actually use a JSON structure to keep the values you are interested in and only read/write when actually needed (load/save event). Hope this helps
I think you have to use a scoped variable in which you store the universalid of the document. This can then be used at any script to initialize the backend document.
From a ssjs you can set a scoped variable using the put method and the get method to read the variable. Example to set and read a scoped variable in session scope :
sessionScope.put(“myvar“,“myvalue“)
sessionScope.get(“myvar“)
To learn more about scoped variables watch this
http://notesin9.com/index.php/2009/11/07/episode-4-intro-to-scoped-variables/
Do different threads accessing method "foo" have their own copy of local variables, or it is needed to make this method synchronized?
class X {
static returnType foo( Object arg) {
Object localvar;
// perform some calculation based on localvar and arg.
// no non-local variable is used i.e: this is a utility method.
// return something.
}
}
You don't need to synchronize that method. The local variable gets created in the current thread's "memory space" and there is no way that it will get accessed by any other thread (from what you've shown above).
Since the variables used are defined/used in it's own scope there is no need for syncronize the method.
The method should not be synchronized but you should use a final variable arg ie
static returnType foo(final Object arg).