Skip to content

Commit

Permalink
Modules: introduced js_shared_dict_zone directive.
Browse files Browse the repository at this point in the history
The directive allows to declare a dictionary that is shared among the
working processes. A dictionary expects strings as keys. It stores
string or number as values. The value type is declared using
type= argument of the directive. The default type is string.

example.conf:
    # Declares a shared dictionary of strings of size 1 Mb that
    # removes key-value after 60 seconds of inactivity.
    js_shared_dict_zone zone=foo:1M timeout=60s;

    # Declares a shared dictionary of strings of size 512Kb that
    # forcibly remove oldest key-value pairs when memory is not enough.
    js_shared_dict_zone zone=bar:512K timeout=30s evict;

    # Declares a permanent number shared dictionary of size 32Kb.
    js_shared_dict_zone zone=num:32k type=number;

example.js:
    function get(r) {
        r.return(200, ngx.shared.foo.get(r.args.key));
    }

    function set(r) {
        r.return(200, ngx.shared.foo.set(r.args.key, r.args.value));
    }

    function delete(r) {
        r.return(200, ngx.shared.bar.delete(r.args.key));
    }

    function increment(r) {
        r.return(200, ngx.shared.num.incr(r.args.key, 2));
    }

In collaboration with Artem S. Povalyukhin, Jakub Jirutka and
洪志道 (Hong Zhi Dao).

This closes #437 issue on Github.
  • Loading branch information
xeioex committed Jul 3, 2023
1 parent 40b01ac commit 1fe63ab
Show file tree
Hide file tree
Showing 10 changed files with 2,390 additions and 6 deletions.
6 changes: 4 additions & 2 deletions nginx/config
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ NJS_LIBXSLT=${NJS_LIBXSLT:-YES}
NJS_ZLIB=${NJS_ZLIB:-YES}

NJS_DEPS="$ngx_addon_dir/ngx_js.h \
$ngx_addon_dir/ngx_js_fetch.h"
$ngx_addon_dir/ngx_js_fetch.h \
$ngx_addon_dir/ngx_js_shared_dict.h"
NJS_SRCS="$ngx_addon_dir/ngx_js.c \
$ngx_addon_dir/ngx_js_fetch.c \
$ngx_addon_dir/ngx_js_regex.c"
$ngx_addon_dir/ngx_js_regex.c \
$ngx_addon_dir/ngx_js_shared_dict.c"

NJS_OPENSSL_LIB=
NJS_XSLT_LIB=
Expand Down
48 changes: 46 additions & 2 deletions nginx/ngx_http_js_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,13 @@ static char *ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_js_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_js_content(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_js_shared_dict_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_js_init_conf_vm(ngx_conf_t *cf,
ngx_js_loc_conf_t *conf);
static void *ngx_http_js_create_main_conf(ngx_conf_t *cf);
static void *ngx_http_js_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
Expand Down Expand Up @@ -393,6 +396,13 @@ static ngx_command_t ngx_http_js_commands[] = {

#endif

{ ngx_string("js_shared_dict_zone"),
NGX_HTTP_MAIN_CONF|NGX_CONF_1MORE,
ngx_http_js_shared_dict_zone,
0,
0,
NULL },

ngx_null_command
};

Expand All @@ -401,7 +411,7 @@ static ngx_http_module_t ngx_http_js_module_ctx = {
NULL, /* preconfiguration */
ngx_http_js_init, /* postconfiguration */

NULL, /* create main configuration */
ngx_http_js_create_main_conf, /* create main configuration */
NULL, /* init main configuration */

NULL, /* create server configuration */
Expand Down Expand Up @@ -775,6 +785,7 @@ static uintptr_t ngx_http_js_uptr[] = {
(uintptr_t) ngx_http_js_fetch_timeout,
(uintptr_t) ngx_http_js_buffer_size,
(uintptr_t) ngx_http_js_max_response_buffer_size,
(uintptr_t) 0 /* main_conf ptr */,
};


Expand All @@ -798,6 +809,7 @@ njs_module_t *njs_http_js_addon_modules[] = {
*/
&ngx_js_ngx_module,
&ngx_js_fetch_module,
&ngx_js_shared_dict_module,
#ifdef NJS_HAVE_OPENSSL
&njs_webcrypto_module,
#endif
Expand Down Expand Up @@ -4149,10 +4161,14 @@ ngx_js_http_init(njs_vm_t *vm)
static ngx_int_t
ngx_http_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)
{
njs_vm_opt_t options;
njs_vm_opt_t options;
ngx_js_main_conf_t *jmcf;

njs_vm_opt_init(&options);

jmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_js_module);
ngx_http_js_uptr[NGX_JS_MAIN_CONF_INDEX] = (uintptr_t) jmcf;

options.backtrace = 1;
options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
options.ops = &ngx_http_js_ops;
Expand Down Expand Up @@ -4292,6 +4308,14 @@ ngx_http_js_content(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}


static char *
ngx_http_js_shared_dict_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
return ngx_js_shared_dict_zone(cf, cmd, conf, &ngx_http_js_module);
}


static char *
ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
Expand Down Expand Up @@ -4330,6 +4354,26 @@ ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}


static void *
ngx_http_js_create_main_conf(ngx_conf_t *cf)
{
ngx_js_main_conf_t *jmcf;

jmcf = ngx_pcalloc(cf->pool, sizeof(ngx_js_main_conf_t));
if (jmcf == NULL) {
return NULL;
}

/*
* set by ngx_pcalloc():
*
* jmcf->dicts = NULL;
*/

return jmcf;
}


static void *
ngx_http_js_create_loc_conf(ngx_conf_t *cf)
{
Expand Down
34 changes: 34 additions & 0 deletions nginx/ngx_js.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ static void ngx_js_cleanup_vm(void *data);
static njs_int_t ngx_js_core_init(njs_vm_t *vm);


static njs_external_t ngx_js_ext_global_shared[] = {

{
.flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
.name.symbol = NJS_SYMBOL_TO_STRING_TAG,
.u.property = {
.value = "GlobalShared",
}
},

{
.flags = NJS_EXTERN_SELF,
.u.object = {
.enumerable = 1,
.prop_handler = njs_js_ext_global_shared_prop,
.keys = njs_js_ext_global_shared_keys,
}
},

};


static njs_external_t ngx_js_ext_core[] = {

{
Expand Down Expand Up @@ -112,6 +134,18 @@ static njs_external_t ngx_js_ext_core[] = {
}
},

{
.flags = NJS_EXTERN_OBJECT,
.name.string = njs_str("shared"),
.enumerable = 1,
.writable = 1,
.u.object = {
.enumerable = 1,
.properties = ngx_js_ext_global_shared,
.nproperties = njs_nitems(ngx_js_ext_global_shared),
}
},

{
.flags = NJS_EXTERN_PROPERTY,
.name.string = njs_str("prefix"),
Expand Down
18 changes: 18 additions & 0 deletions nginx/ngx_js.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <ngx_core.h>
#include <njs.h>
#include "ngx_js_fetch.h"
#include "ngx_js_shared_dict.h"


#define NGX_JS_UNSET 0
Expand Down Expand Up @@ -43,6 +44,9 @@ typedef ngx_flag_t (*ngx_external_size_pt)(njs_vm_t *vm,
njs_external_ptr_t e);
typedef ngx_ssl_t *(*ngx_external_ssl_pt)(njs_vm_t *vm, njs_external_ptr_t e);


typedef struct ngx_js_dict_s ngx_js_dict_t;

typedef struct {
ngx_str_t name;
ngx_str_t path;
Expand All @@ -51,6 +55,10 @@ typedef struct {
} ngx_js_named_path_t;


#define NGX_JS_COMMON_MAIN_CONF \
ngx_js_dict_t *dicts \


#define _NGX_JS_COMMON_LOC_CONF \
njs_vm_t *vm; \
ngx_array_t *imports; \
Expand Down Expand Up @@ -80,6 +88,11 @@ typedef struct {
#endif


typedef struct {
NGX_JS_COMMON_MAIN_CONF;
} ngx_js_main_conf_t;


typedef struct {
NGX_JS_COMMON_LOC_CONF;
} ngx_js_loc_conf_t;
Expand All @@ -105,6 +118,9 @@ typedef struct {
((ngx_external_size_pt) njs_vm_meta(vm, 8))(vm, e)
#define ngx_external_max_response_buffer_size(vm, e) \
((ngx_external_size_pt) njs_vm_meta(vm, 9))(vm, e)
#define NGX_JS_MAIN_CONF_INDEX 10
#define ngx_main_conf(vm) \
((ngx_js_main_conf_t *) njs_vm_meta(vm, NGX_JS_MAIN_CONF_INDEX))


#define ngx_js_prop(vm, type, value, start, len) \
Expand Down Expand Up @@ -134,6 +150,8 @@ ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf,
ngx_js_loc_conf_t *ngx_js_create_conf(ngx_conf_t *cf, size_t size);
char * ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child,
ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf));
char *ngx_js_shared_dict_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf,
void *tag);

njs_int_t ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop,
njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
Expand Down
Loading

0 comments on commit 1fe63ab

Please sign in to comment.