subrepo: subdir: "deps/nats.c" merged: "5d057f6" upstream: origin: "https://github.com/nats-io/nats.c.git" branch: "v3.7.0" commit: "5d057f6" git-subrepo: version: "0.4.6" commit: "affc4c01a"
192 lines
5.9 KiB
C
192 lines
5.9 KiB
C
// Copyright 2023 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "examples.h"
|
|
|
|
// Sequence NATS microservice example.
|
|
//
|
|
// This example illustrates multiple NATS microservices communicating with each
|
|
// other.
|
|
//
|
|
// The main service (c-sequence) calculates the sum of 1/f(1) + 1/f(2)... up to
|
|
// N (included). It exposes one (default) endpoint, "sequence". The inputs are
|
|
// f (the function name) and N. name, can be "factorial", "fibonacci", or
|
|
// "power2").
|
|
//
|
|
// c-sequence parses the request, then calculates the sequence by calling the
|
|
// c-functions microservice to calculate f(1), f(2), etc. The c-functions
|
|
// service in turn uses c-arithmetics microservice for all arithmetic
|
|
// operations.
|
|
//
|
|
// Requires NATS server and CLI, and the nats.c examples fully built. See
|
|
// https://github.com/nats-io/nats.c#building
|
|
//
|
|
// RUN:
|
|
// ```sh
|
|
// $NATS_SERVER & # NATS_SERVER points to the NATS server binary
|
|
// nats_pid=$!
|
|
// sleep 2 # wait for server to start
|
|
// ./examples/nats-micro-sequence &
|
|
// sequence_pid=$!
|
|
// ./examples/nats-micro-func &
|
|
// func_pid=$!
|
|
// ./examples/nats-micro-arithmetics &
|
|
// arithmetics_pid=$!
|
|
// sleep 2 # wait for microservice to start
|
|
// nats request -r 'sequence' '"factorial" 10'
|
|
// nats request -r 'sequence' '"power2" 10'
|
|
// nats request -r 'sequence' '"fibonacci" 10'
|
|
// kill $sequence_pid $func_pid $arithmetics_pid $nats_pid
|
|
// ```
|
|
//
|
|
// OUTPUT:
|
|
// ```
|
|
// 2.718282
|
|
// 1.999023
|
|
// 3.341705
|
|
// ```
|
|
|
|
static microError *
|
|
call_function(long double *result, natsConnection *nc, const char *subject, int n)
|
|
{
|
|
microError *err = NULL;
|
|
microClient *client = NULL;
|
|
natsMsg *response = NULL;
|
|
microArgs *args = NULL;
|
|
char buf[256];
|
|
char sbuf[256];
|
|
int len;
|
|
|
|
len = snprintf(buf, sizeof(buf), "%d", n);
|
|
snprintf(sbuf, sizeof(sbuf), "f.%s", subject);
|
|
err = micro_NewClient(&client, nc, NULL);
|
|
if (err == NULL)
|
|
err = microClient_DoRequest(&response, client, sbuf, buf, len);
|
|
if (err == NULL)
|
|
err = micro_ParseArgs(&args, natsMsg_GetData(response), natsMsg_GetDataLength(response));
|
|
if (err == NULL)
|
|
err = microArgs_GetFloat(result, args, 0);
|
|
|
|
microClient_Destroy(client);
|
|
natsMsg_Destroy(response);
|
|
return err;
|
|
}
|
|
|
|
// calculates the sum of X/f(1) + X/f(2)... up to N (included). The inputs are X
|
|
// (float), f name (string), and N (int). E.g.: '10.0 "power2" 10' will
|
|
// calculate 10/2 + 10/4 + 10/8 + 10/16 + 10/32 + 10/64 + 10/128 + 10/256 +
|
|
// 10/512 + 10/1024 = 20.998046875
|
|
static microError *handle_sequence(microRequest *req)
|
|
{
|
|
microError *err = NULL;
|
|
natsConnection *nc = microRequest_GetConnection(req);
|
|
microArgs *args = NULL;
|
|
int n = 0;
|
|
int i;
|
|
const char *function;
|
|
long double initialValue = 1.0;
|
|
long double value = 1.0;
|
|
long double denominator = 0;
|
|
char result[64];
|
|
int result_len = 0;
|
|
|
|
err = micro_ParseArgs(&args, microRequest_GetData(req), microRequest_GetDataLength(req));
|
|
if ((err == NULL) && (microArgs_Count(args) != 2))
|
|
{
|
|
err = micro_Errorf("Invalid number of arguments, expected 2 got %d", microArgs_Count(args));
|
|
}
|
|
|
|
if (err == NULL)
|
|
err = microArgs_GetString(&function, args, 0);
|
|
if ((err == NULL) &&
|
|
(strcmp(function, "factorial") != 0) &&
|
|
(strcmp(function, "power2") != 0) &&
|
|
(strcmp(function, "fibonacci") != 0))
|
|
{
|
|
err = micro_Errorf("Invalid function name '%s', must be 'factorial', 'power2', or 'fibonacci'", function);
|
|
}
|
|
if (err == NULL)
|
|
err = microArgs_GetInt(&n, args, 1);
|
|
if ((err == NULL) && (n < 1))
|
|
{
|
|
err = micro_Errorf("Invalid number of iterations %d, must be at least 1", n);
|
|
}
|
|
|
|
for (i = 1; (err == NULL) && (i <= n); i++)
|
|
{
|
|
if (err == NULL)
|
|
err = call_function(&denominator, nc, function, i);
|
|
if ((err == NULL) && (denominator == 0))
|
|
{
|
|
err = micro_Errorf("division by zero at step %d", i);
|
|
}
|
|
if (err == NULL)
|
|
value = value + initialValue / denominator;
|
|
}
|
|
|
|
if (err == NULL)
|
|
result_len = snprintf(result, sizeof(result), "%Lf", value);
|
|
if (err == NULL)
|
|
err = microRequest_Respond(req, result, result_len);
|
|
|
|
microArgs_Destroy(args);
|
|
return err;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
natsStatus s = NATS_OK;
|
|
microError *err = NULL;
|
|
natsConnection *conn = NULL;
|
|
natsOptions *opts = NULL;
|
|
microService *m = NULL;
|
|
char errorbuf[1024];
|
|
|
|
microEndpointConfig sequence_cfg = {
|
|
.Subject = "sequence",
|
|
.Name = "sequence-service",
|
|
.Handler = handle_sequence,
|
|
};
|
|
microServiceConfig cfg = {
|
|
.Description = "Sequence adder - NATS microservice example in C",
|
|
.Name = "c-sequence",
|
|
.Version = "1.0.0",
|
|
.Endpoint = &sequence_cfg,
|
|
};
|
|
|
|
opts = parseArgs(argc, argv, "");
|
|
s = natsConnection_Connect(&conn, opts);
|
|
if (s != NATS_OK)
|
|
{
|
|
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
|
nats_PrintLastErrorStack(stderr);
|
|
natsOptions_Destroy(opts);
|
|
return 1;
|
|
}
|
|
|
|
err = micro_AddService(&m, conn, &cfg);
|
|
if (err == NULL)
|
|
err = microService_Run(m);
|
|
|
|
microService_Destroy(m);
|
|
natsOptions_Destroy(opts);
|
|
natsConnection_Destroy(conn);
|
|
if (err != NULL)
|
|
{
|
|
printf("Error: %s\n", microError_String(err, errorbuf, sizeof(errorbuf)));
|
|
microError_Destroy(err);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|