Collection of small Common Lisp libraries
These libraries contain code originally extracted from ITA's runtime system, QUUX.
gRPC implementation for Common Lisp
License: MIT License
I have given an issue before #44. I said I found the solution; actually, it isn't.
The PR #45 give the cffi
the name of the lib it needs to load. (:default "libgrpc")
let it load the libgrpc.dylib
which homebrew installed. However, libraries.lisp
need to load the grpc.so
it compiled inside this repo.
;; Load the C wrapper directly from the source directory.
(t (:default #.(namestring
(asdf:system-relative-pathname "grpc" "grpc"))))
let cffi read the grpc.dylib
when in :darwin
platform. But the Makefile compiles the grpc.so
in the source folder rather than .dylib
file. So my PR only let this package doesn't give the error, but it cannot work.
I made some changes and wrote a demo, found the way that libraries.lisp
read successfully and can work.
solution 1:
let libraries.lisp
read the .so
file in :darwin
(:darwin #.(namestring
(asdf:system-relative-pathname "grpc" "grpc.so")))
it is the easiest way to make it I think.
solution 2:
let makefile compile .dylib
file in :darwin
.
default_target: grpc.so
=> default_target: grpc.dylib
.
Give a condition that compiles .dylib
when in macos. However, it has to change the makefile.
What do you guys think? If you guys also agree the first way is acceptable, I can give the PR to fix it (which is the issue I made, sorry about that).
I am looking to use this library connect a common lisp service to a bunch of gRPC servers.
As a first step, I am trying to get a minimal product working, specifically an insecure connection using unary calls.
I have the below c++ helloworld server running and can successfully connect the below c++ client to it. However the common lisp client does not connect.
My Environment is:
Below is the error I receive when attempting to connect. I get this error regardless of whether the server is running or not.
I get this error with the common lisp client regardless of whether the server is running or not.
The C++ client works when the server is running and gives me correct error 14: failed to connect to all addresses
when the server is not running.
For troubleshooting I pointed the common lisp client and the c++ client to a netcat instance to capture of the connection traffic. Unfortunately it looks like the common lisp client doesn't attempt a network connection whereas the c++ client does send some data to netcat.
I have exhausted my troubleshooting efforts, any hints from your end would be greatly appreciated.
GRPC CALL ERROR: GRPC-STATUS-UNAVAILABLE.
[Condition of type GRPC::GRPC-CALL-ERROR]
Restarts:
0: [RETRY] Retry SLY mREPL evaluation request.
1: [*ABORT] Return to SLY's top level.
2: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {1001530003}>)
Backtrace:
0: (GRPC::CHECK-SERVER-STATUS #.(SB-SYS:INT-SAP #X7FA35C0855C0) 1)
Locals:
OPS = #.(SB-SYS:INT-SAP #X7FA35C0855C0)
RECEIVE-STATUS-ON-CLIENT-INDEX = 1
1: (GRPC::SEND-MESSAGE #S(GRPC::CALL :C-CALL #.(SB-SYS:INT-SAP #X7FA35C07CBB0) :C-TAG #.(SB-SYS:INT-SAP #X7FA35C07CAF0) :C-OPS #.(SB-SYS:INT-SAP #X7FA35C0855C0) :OPS-PLIST (:RECV-METADATA 2 :CLIENT-RE\
CV-..
Locals:
BYTES-TO-SEND = #(10 3 78 101 111)
CALL = #S(GRPC::CALL ..)
2: (GRPC:GRPC-CALL #.(SB-SYS:INT-SAP #X7FA35C085250) "/helloworld.Greeter/SayHello" #(10 3 78 101 111) NIL NIL)
Locals:
BYTES-TO-SEND = #(10 3 78 101 111)
CALL = #S(GRPC::CALL ..)
CHANNEL = #.(SB-SYS:INT-SAP #X7FA35C085250)
CLIENT-STREAM = NIL
SERVER-STREAM = NIL
SERVICE-METHOD-NAME = "/helloworld.Greeter/SayHello"
3: ((:METHOD GRPC::START-CALL (T T T T)) #.(SB-SYS:INT-SAP #X7FA35C085250) #<CL-PROTOBUFS:METHOD-DESCRIPTOR CL-PROTOBUFS.HELLOWORLD::SAY-HELLO (CL-PROTOBUFS.HELLOWORLD:HELLO-REQUEST) => (CL-PROTOBUFS.\
HEL..
Locals:
GRPC::CHANNEL = #.(SB-SYS:INT-SAP #X7FA35C085250)
#:G10 = NIL
METHOD = #<CL-PROTOBUFS:METHOD-DESCRIPTOR CL-PROTOBUFS.HELLOWORLD::SAY-HELLO (CL-PROTOBUFS.HELLOWORLD:HELLO-REQUEST) => (CL-PROTOBUFS.HELLOWORLD:HELLO-REPLY) {1002C1ACE3}>
GRPC::OUTPUT-TYPE = CL-PROTOBUFS.HELLOWORLD:HELLO-REPLY
GRPC::REQUEST = #S(CL-PROTOBUFS.HELLOWORLD:HELLO-REQUEST :%%SKIPPED-BYTES NIL :%NAME "Neo" :%%BYTES NIL :%%IS-SET #*)
GRPC::RESPONSE = NIL
GRPC::SERVER-STREAM = NIL
4: (AGENTS::GRPC-MAIN)
Locals:
CHANNEL = #.(SB-SYS:INT-SAP #X7FA35C085250)
5: (SB-INT:SIMPLE-EVAL-IN-LEXENV (AGENTS::GRPC-MAIN) #<NULL-LEXENV>)
6: (EVAL (AGENTS::GRPC-MAIN))
7: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
--more--
(defpackage agents
(:use :cl)
(:local-nicknames (#:helloworld #:cl-protobufs.helloworld)
(#:helloworld-rpc #:cl-protobufs.helloworld-rpc)))
(in-package :agents)
(defun grpc-main ()
(grpc:init-grpc)
(grpc:with-insecure-channel
(channel (concatenate 'string "10.162.22.100" ":" (write-to-string 50051)))
;; Unary streaming
(format nil "Trying unary call")
(let* ((message (helloworld:make-hello-request :name "Neo"))
(response (helloworld-rpc:call-say-hello channel message)))
(format t "Channel: ~A~%" channel)
(format t "Message: ~S~%" message)
(format t "Response: ~S~%" response)))
(grpc:shutdown-grpc))
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
std::cout << prefix + request->name() << std::endl;
return Status::OK;
}
};
std::string readFileIntoString(const std::string& path) {
std::ifstream input_file(path);
if (!input_file.is_open()) {
std::cerr << "Could not open the file - '" << path << "'" << std::endl;
}
return std::string((std::istreambuf_iterator<char>(input_file)),
std::istreambuf_iterator<char>());
}
bool fileExists(const std::string& path) {
std::ifstream f(path.c_str());
return f.good();
}
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
std::shared_ptr<grpc::ServerCredentials> creds;
// Set up authentication mechanism (or lack therof) for the server.
auto auth_mechanism = "insecure";
if (auth_mechanism == "insecure") {
creds = grpc::InsecureServerCredentials();
}
builder.AddListeningPort(server_address, creds);
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
std::cout << prefix + request->name() << std::endl;
return Status::OK;
}
};
std::string readFileIntoString(const std::string& path) {
std::ifstream input_file(path);
if (!input_file.is_open()) {
std::cerr << "Could not open the file - '" << path << "'" << std::endl;
}
return std::string((std::istreambuf_iterator<char>(input_file)),
std::istreambuf_iterator<char>());
}
bool fileExists(const std::string& path) {
std::ifstream f(path.c_str());
return f.good();
}
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
std::shared_ptr<grpc::ServerCredentials> creds;
// Set up authentication mechanism (or lack therof) for the server.
auto auth_mechanism = "insecure";
if (auth_mechanism == "insecure") {
creds = grpc::InsecureServerCredentials();
}
builder.AddListeningPort(server_address, creds);
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}
syntax = "proto3";
option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
I'm attempting to add additional metadata alongside my request.
An example utilizing ruby would be
response = stub.rpc_call(req, {metadata: {key1: value1, key2: value2}})
Does similar functionality exist within this library?
I have installed the cl-protobufs and the (ql:quickload "cl-protobufs")
has no error in REPL.
But when I was trying to (ql:quickload "grpc")
, I get the error message below return
Unable to load foreign library (GRPC-CLIENT-WRAPPER).
Error opening shared object "/Users/{username}/quicklisp/local-projects/grpc/grpc.dylib":
dlopen(/Users/{username}/quicklisp/local-projects/grpc/grpc.dylib, 0x000A): tried: '/Users/{username}/quicklisp/local-projects/grpc/grpc.dylib' (no such file).
Do I mess up the path or I need to do something else to generate the grpc.dylib
like the protoc-gen-cl-pb
in cl-protobufs
?
Thank you
grpc and cl-protobufs: master branch version.
protoc: libprotoc 3.21.4
runtime: SBCL
OS: macos 12.5
Hi, guys!
Recently I did a wrapper around JSONRPC to generate OpenRPC spec and CL client for a service described by a spec: https://40ants.com/openrpc/
Don't know if OpenRPC is applicable to gRPC, but in case if you wanna add support, I'll be happy to extend my system and support gRPC besides JSON-RPC.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.