Added a Redis/Valkey extension named redis. (0.42.0)
This commit is contained in:
parent
06072576fc
commit
cbb81c0b93
28 changed files with 798 additions and 15 deletions
45
src/vm/redis/close.c
Normal file
45
src/vm/redis/close.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file close.c
|
||||
* @brief Implements the OP_REDIS_CLOSE opcode (conditional build).
|
||||
*
|
||||
* Closes a previously opened Redis connection and removes its registry entry.
|
||||
*
|
||||
* Stack effect
|
||||
* ------------
|
||||
* OP_REDIS_CLOSE: (handle:int) -> Nil
|
||||
*
|
||||
* Behavior
|
||||
* --------
|
||||
* - When FUN_WITH_REDIS is enabled, looks up the handle, calls redisFree() on
|
||||
* the underlying connection if present, clears the pointer, and removes the
|
||||
* registry entry. Always pushes Nil.
|
||||
* - When FUN_WITH_REDIS is disabled, pops the argument and pushes Nil.
|
||||
*/
|
||||
|
||||
case OP_REDIS_CLOSE: {
|
||||
#ifdef FUN_WITH_REDIS
|
||||
Value vh = pop_value(vm);
|
||||
int hid = (int)vh.i;
|
||||
free_value(vh);
|
||||
RedisHandle *h = redis_reg_get(hid);
|
||||
if (h && h->ctx) {
|
||||
redisFree(h->ctx);
|
||||
h->ctx = NULL;
|
||||
}
|
||||
redis_reg_del(hid);
|
||||
push_value(vm, make_nil());
|
||||
#else
|
||||
Value v1 = pop_value(vm); free_value(v1);
|
||||
push_value(vm, make_nil());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
58
src/vm/redis/cmd.c
Normal file
58
src/vm/redis/cmd.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cmd.c
|
||||
* @brief Implements the OP_REDIS_CMD opcode (conditional build).
|
||||
*
|
||||
* Executes a Redis command using the synchronous hiredis API on a previously
|
||||
* opened handle and converts the reply to a Fun Value.
|
||||
*
|
||||
* Stack effect
|
||||
* ------------
|
||||
* OP_REDIS_CMD: (handle:int, cmd:string) -> reply:Value
|
||||
*
|
||||
* Behavior
|
||||
* --------
|
||||
* - The command string uses Redis inline protocol formatting (e.g.,
|
||||
* "PING", "SET key val", "LRANGE list 0 -1").
|
||||
* - When FUN_WITH_REDIS is enabled, the opcode looks up the connection by
|
||||
* handle id, issues redisCommand(), and converts the resulting reply to a
|
||||
* Fun Value:
|
||||
* - status/string -> string
|
||||
* - integer -> int
|
||||
* - nil -> nil
|
||||
* - array -> array of converted elements
|
||||
* On errors or lookup failures, pushes Nil.
|
||||
* - When FUN_WITH_REDIS is disabled, pops arguments and pushes Nil.
|
||||
*/
|
||||
|
||||
case OP_REDIS_CMD: {
|
||||
#ifdef FUN_WITH_REDIS
|
||||
Value vcmd = pop_value(vm);
|
||||
Value vh = pop_value(vm);
|
||||
int hid = (int)vh.i;
|
||||
char *cmd = value_to_string_alloc(&vcmd);
|
||||
free_value(vh);
|
||||
free_value(vcmd);
|
||||
RedisHandle *h = redis_reg_get(hid);
|
||||
if (!h || !h->ctx || !cmd) { if (cmd) free(cmd); push_value(vm, make_nil()); break; }
|
||||
redisReply *r = (redisReply *)redisCommand(h->ctx, cmd);
|
||||
free(cmd);
|
||||
if (!r) { push_value(vm, make_nil()); break; }
|
||||
Value out = hiredis_reply_to_value(r);
|
||||
freeReplyObject(r);
|
||||
push_value(vm, out);
|
||||
#else
|
||||
Value v1 = pop_value(vm); free_value(v1);
|
||||
Value v2 = pop_value(vm); free_value(v2);
|
||||
push_value(vm, make_nil());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
65
src/vm/redis/connect.c
Normal file
65
src/vm/redis/connect.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect.c
|
||||
* @brief Implements the OP_REDIS_CONNECT opcode (conditional build).
|
||||
*
|
||||
* Establishes a synchronous TCP connection to a Redis-compatible server using
|
||||
* hiredis and registers the connection handle in the internal registry.
|
||||
*
|
||||
* Stack effect
|
||||
* ------------
|
||||
* OP_REDIS_CONNECT: (host:string, port:int) -> handle:int (>0) or 0 on error
|
||||
*
|
||||
* Behavior
|
||||
* --------
|
||||
* - When FUN_WITH_REDIS is enabled, attempts a blocking connect with a
|
||||
* 2-second timeout via redisConnectWithTimeout(). On success, the created
|
||||
* redisContext* is stored in the registry and the assigned positive handle
|
||||
* id is pushed. On failure, 0 is pushed.
|
||||
* - When FUN_WITH_REDIS is disabled, arguments are popped and 0 is pushed.
|
||||
*
|
||||
* Notes
|
||||
* -----
|
||||
* - The returned handle must be closed with OP_REDIS_CLOSE to release
|
||||
* resources and delete the registry entry.
|
||||
*/
|
||||
|
||||
case OP_REDIS_CONNECT: {
|
||||
#ifdef FUN_WITH_REDIS
|
||||
Value vport = pop_value(vm);
|
||||
Value vhost = pop_value(vm);
|
||||
int port = (int)vport.i;
|
||||
char *host = value_to_string_alloc(&vhost);
|
||||
free_value(vport);
|
||||
free_value(vhost);
|
||||
if (!host) { push_value(vm, make_int(0)); break; }
|
||||
struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0;
|
||||
redisContext *ctx = redisConnectWithTimeout(host, port, tv);
|
||||
free(host);
|
||||
if (!ctx || ctx->err) {
|
||||
if (ctx) redisFree(ctx);
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
RedisHandle *h = redis_reg_add(ctx);
|
||||
if (!h) {
|
||||
redisFree(ctx);
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
push_value(vm, make_int(h->id));
|
||||
#else
|
||||
Value v1 = pop_value(vm); free_value(v1);
|
||||
Value v2 = pop_value(vm); free_value(v2);
|
||||
push_value(vm, make_int(0));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue