stepancheg / grpc-rust

Rust implementation of gRPC
MIT License
1.38k stars 124 forks source link

Changing value in service struct #14

Closed aptakhin closed 7 years ago

aptakhin commented 7 years ago

Hi Stepan!

Is there a way to change some internal value in service struct? I tried to add mut to fn Set(&mut self, req: Value) -> GrpcResult<Value> signature, but of course it doesn't compiles because generated traits mismatch.

error[E0053]: method `Set` has an incompatible type for trait
  --> src/test/bin/main.rs:22:5
   |
22 |     fn Set(&mut self, req: Value) -> GrpcResult<Value> {
   |     ^ types differ in mutability
   |
   = note: expected type `fn(&MutableServiceImpl, deqalib::test::Value) -> std::result::Result<deqalib::test::Value, grpc::error::GrpcError>`
   = note:    found type `fn(&mut MutableServiceImpl, deqalib::test::Value) -> std::result::Result<deqalib::test::Value, grpc::error::GrpcError>`

error: aborting due to previous error

Example proto:

package test;

service MutableService {
    rpc Set (Value) returns (Value) {}
}

message Value {
    optional string value = 1;
}

Example source:

extern crate grpc;
extern crate deqalib;

use grpc::result::GrpcResult;
use deqalib::test::*;
use deqalib::test_grpc::*;
use std::thread;

struct MutableServiceImpl {
    value: String,
}

impl MutableServiceImpl {
    fn new() -> MutableServiceImpl {
        MutableServiceImpl { value: String::new() }
    }
}

impl MutableService for MutableServiceImpl {
    fn Set(&mut self, req: Value) -> GrpcResult<Value> {
        self.value = req.get_value().to_owned();
        Ok(Value::new())
    }
}

fn main() {
    let _server = MutableServiceServer::new(50051, MutableServiceImpl::new());
    loop {
        thread::park();
    }
}
stepancheg commented 7 years ago

Self parameter is immutable intentionally. If you need mutable state, you need to store it for example in Arc<Mutex<T>>:

struct MutableServiceImpl {
    value: Arc<Mutex<String>>,
}

impl MutableService for MutableServiceImpl {
    fn Set(&self, req: Value) -> GrpcResult<Value> {
        *self.value.lock().uwrap() = req.get_value().to_owned();
        Ok(Value::new())
    }
}

Set operation can be executed concurrently, so self should be protected against access from multiple threads.

aptakhin commented 7 years ago

Cool! It works. Thank you.

aptakhin commented 7 years ago

And later I saw that it was a duplicate issue, sorry. I'll try to PR some docs here.

stepancheg commented 7 years ago

No problem, I'm glad to help.

PR is of course always welcome.