Skip to content

Premature EOF error #73

@farooq545f

Description

@farooq545f

Every time i run the grpcurl --plaintext localhost:9092 Currency.SubscribeRates command i get 2

024-09-27T14:46:54.415+0530 [INFO] Client has closed connection that is EOF error

if i run the command grpcurl --plaintext -d '{"Base": "USD", "Destination": "EUR"}' localhost:9092 Currency.SubscribeRates

I am getting
2024-09-27T14:47:08.530+0530 [INFO] Handle client request: request_base=USD request_dest=EUR
2024-09-27T14:47:08.530+0530 [INFO] Client has closed connection

Basically once the grpc curl command is made it will not take any input from client side thus failing the bi directional nature

below are my protos and currency server file

syntax = "proto3";

option go_package = "microservices-go/currency/protos;currencypb";

service Currency {
    // GetRate returns the exchange rate for the two provided currency codes 
    
    rpc GetRate(RateRequest) returns (RateResponse);

    // SubscribeRates allows a client to subscribe for changes in an exchange rate
    // when the rate changes a response will be sent

    rpc SubscribeRates(stream RateRequest) returns(stream RateResponse);

}

// RateRequest defines the request for a GetRate call
message RateRequest {
    // Base is the base currency code for the rate
    Currencies Base = 1;
    
    // Destination is the destination currency code for the rate
    Currencies Destination = 2;
}

// RateResponse is the response from a GetRate call, it contains
// rate which is a floating point number and can be used to convert between the 
// two currencies specified in the request.
message RateResponse {
    double rate = 1;
}

// Currencies is an enum which represents the allowed currencies for the API
enum Currencies {
  EUR=0;
  USD=1;
  JPY=2;
  BGN=3;
  CZK=4;
  DKK=5;
  GBP=6;
  HUF=7;
  PLN=8;
  RON=9;
  SEK=10;
  CHF=11;
  ISK=12;
  NOK=13;
  HRK=14;
  RUB=15;
  TRY=16;
  AUD=17;
  BRL=18;
  CAD=19;
  CNY=20;
  HKD=21;
  IDR=22;
  ILS=23;
  INR=24;
  KRW=25;
  MXN=26;
  MYR=27;
  NZD=28;
  PHP=29;
  SGD=30;
  THB=31;
  ZAR=32;
}


package server

import (
	"context"
	"fmt"
	"io"
	"time"

	"github.com/hashicorp/go-hclog"
	"github.com/umar545f/go-microservices/currency/data"
	currencypb "github.com/umar545f/go-microservices/currency/protos/currency"
)

// Currency is a gRPC server it implements the methods defined by the CurrencyServer interface
type Currency struct {
	log hclog.Logger
	currencypb.UnimplementedCurrencyServer
	rates data.ExchangeRates
}

// NewCurrency creates a new Currency server
func NewCurrency(log hclog.Logger, rates *data.ExchangeRates) *Currency {
	return &Currency{log, currencypb.UnimplementedCurrencyServer{}, *rates}
}

// GetRate implements the CurrencyServer GetRate method and returns the currency exchange rate
// for the two given currencies.
func (c *Currency) GetRate(ctx context.Context, rr *currencypb.RateRequest) (*currencypb.RateResponse, error) {
	c.log.Info("Handle request for GetRate", "base", rr.GetBase(), "dest", rr.GetDestination())

	rate, err := c.rates.GetRate(rr.GetBase().String(), rr.GetDestination().String())

	if err != nil {
		fmt.Println("error while getting rates", err)
	}

	return &currencypb.RateResponse{Rate: rate}, nil
}

//// SubscribeRates implments the gRPC bidirection streaming method for the server

func (c *Currency) SubscribeRates(src currencypb.Currency_SubscribeRatesServer) error {
	go func() {
		for {
			rr, err := src.Recv() // Recv is a blocking method which returns on client data

			// io.EOF signals that the client has closed the connection

			if err == io.EOF {
				c.log.Info("Client has closed connection")
				break
			}

			if err != nil {
				c.log.Error("Unable to read from client", "error", err)
				break
			}

			c.log.Info("Handle client request", "request_base", rr.GetBase(),
				"request_dest", rr.GetDestination())

		}
	}()

	// handle server responses
	// we block here to keep the connection open
	for {
		// send a message back to the client
		err := src.Send(&currencypb.RateResponse{Rate: 12.1})
		if err != nil {
			return err
		}

		time.Sleep(5 * time.Second)
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions