diff --git a/cmd/count-client/main.go b/cmd/count-client/main.go index 81de989..2134ab6 100644 --- a/cmd/count-client/main.go +++ b/cmd/count-client/main.go @@ -2,13 +2,83 @@ package main import ( "fmt" + "flag" + "time" + "log" "os" + "context" "github.com/therecipe/qt/widgets" + "github.com/jordanorelli/grpc-ui/lib/count" + "google.golang.org/grpc" ) +var ( + info_log *log.Logger + error_log *log.Logger +) + +func bg(label *widgets.QLabel) { + info_log.Println("bg goroutine started") + defer info_log.Println("bg goroutine exited") + + time.Sleep(5*time.Second) + conn, err := grpc.Dial("localhost:9001", grpc.WithInsecure()) + if err != nil { + label.SetText(fmt.Sprintf("error: %v", err)) + return + } + + req := count.NextRequest{Name: "example-param"} + client := count.NewCountClient(conn) + for range time.Tick(time.Second) { + reply, err := client.Next(context.TODO(), &req) + if err != nil { + label.SetText(fmt.Sprintf("error: %v", err)) + continue + } + label.SetText(fmt.Sprintf("count: %v", reply.GetVal())) + } + + label.SetText(fmt.Sprintf("Connection: %v", conn)) +} + func main() { - fmt.Println("Hey from VSCode") + var options struct { + infoLogPath string + errorLogPath string + } + flag.StringVar(&options.infoLogPath, "info-log", "count-client.log", "file path of an info log") + flag.StringVar(&options.errorLogPath, "error-log", "count-client.log", "file path of an error log") + flag.Parse() + + { + f, err := os.OpenFile(options.infoLogPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + if err != nil { + panic(err) + } + info_log = log.New(f, "i ", log.LstdFlags) + } + + { + f, err := os.OpenFile(options.errorLogPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + if err != nil { + panic(err) + } + error_log = log.New(f, "e ", log.LstdFlags) + } + widgets.NewQApplication(len(os.Args), os.Args) - widgets.QApplication_Exec() + + label := widgets.NewQLabel(nil, 0) + label.SetText("this is a label") + label.Show() + + info_log.Println("spawning bg goroutine") + go bg(label) + + info_log.Println("starting qapplication") + code := widgets.QApplication_Exec() + info_log.Printf("QApplication exited with code: %d\n", code) + os.Exit(code) } \ No newline at end of file diff --git a/cmd/count-server/main.go b/cmd/count-server/main.go new file mode 100644 index 0000000..b2f3983 --- /dev/null +++ b/cmd/count-server/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "net" + "sync" + "google.golang.org/grpc" + "golang.org/x/net/context" + "github.com/jordanorelli/grpc-ui/lib/count" +) + +type countServer struct { + sync.Mutex + last int64 +} + +func (c *countServer) Next(ctx context.Context, r *count.NextRequest) (*count.NextReply, error) { + return &count.NextReply{Val: c.incr()}, nil +} + +func (c *countServer) incr() int64 { + c.Lock() + defer c.Unlock() + + c.last += 1 + return c.last +} + +func main() { + lis, err := net.Listen("tcp", "localhost:9001") + if err != nil { + panic(err) + } + + s := grpc.NewServer() + count.RegisterCountServer(s, &countServer{}) + s.Serve(lis) +} \ No newline at end of file diff --git a/lib/count.proto b/lib/count.proto new file mode 100644 index 0000000..e1d2a68 --- /dev/null +++ b/lib/count.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +service Count { + rpc Next (NextRequest) returns (NextReply) {} +} + +message NextRequest { + string name = 1; +} + +message NextReply { + int64 val = 1; +} \ No newline at end of file diff --git a/lib/count/count.pb.go b/lib/count/count.pb.go new file mode 100644 index 0000000..0fe0276 --- /dev/null +++ b/lib/count/count.pb.go @@ -0,0 +1,158 @@ +// Code generated by protoc-gen-go. +// source: count.proto +// DO NOT EDIT! + +/* +Package count is a generated protocol buffer package. + +It is generated from these files: + count.proto + +It has these top-level messages: + NextRequest + NextReply +*/ +package count + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type NextRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *NextRequest) Reset() { *m = NextRequest{} } +func (m *NextRequest) String() string { return proto.CompactTextString(m) } +func (*NextRequest) ProtoMessage() {} +func (*NextRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *NextRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +type NextReply struct { + Val int64 `protobuf:"varint,1,opt,name=val" json:"val,omitempty"` +} + +func (m *NextReply) Reset() { *m = NextReply{} } +func (m *NextReply) String() string { return proto.CompactTextString(m) } +func (*NextReply) ProtoMessage() {} +func (*NextReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *NextReply) GetVal() int64 { + if m != nil { + return m.Val + } + return 0 +} + +func init() { + proto.RegisterType((*NextRequest)(nil), "NextRequest") + proto.RegisterType((*NextReply)(nil), "NextReply") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Count service + +type CountClient interface { + Next(ctx context.Context, in *NextRequest, opts ...grpc.CallOption) (*NextReply, error) +} + +type countClient struct { + cc *grpc.ClientConn +} + +func NewCountClient(cc *grpc.ClientConn) CountClient { + return &countClient{cc} +} + +func (c *countClient) Next(ctx context.Context, in *NextRequest, opts ...grpc.CallOption) (*NextReply, error) { + out := new(NextReply) + err := grpc.Invoke(ctx, "/Count/Next", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Count service + +type CountServer interface { + Next(context.Context, *NextRequest) (*NextReply, error) +} + +func RegisterCountServer(s *grpc.Server, srv CountServer) { + s.RegisterService(&_Count_serviceDesc, srv) +} + +func _Count_Next_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NextRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CountServer).Next(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/Count/Next", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CountServer).Next(ctx, req.(*NextRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Count_serviceDesc = grpc.ServiceDesc{ + ServiceName: "Count", + HandlerType: (*CountServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Next", + Handler: _Count_Next_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "count.proto", +} + +func init() { proto.RegisterFile("count.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 121 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0xce, 0x2f, 0xcd, + 0x2b, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x52, 0xe4, 0xe2, 0xf6, 0x4b, 0xad, 0x28, 0x09, + 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 0xe2, 0x62, 0xc9, 0x4b, 0xcc, 0x4d, 0x95, 0x60, + 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x95, 0x64, 0xb9, 0x38, 0x21, 0x4a, 0x0a, 0x72, 0x2a, + 0x85, 0x04, 0xb8, 0x98, 0xcb, 0x12, 0x73, 0xc0, 0xf2, 0xcc, 0x41, 0x20, 0xa6, 0x91, 0x36, 0x17, + 0xab, 0x33, 0xc8, 0x40, 0x21, 0x25, 0x2e, 0x16, 0x90, 0x3a, 0x21, 0x1e, 0x3d, 0x24, 0x13, 0xa5, + 0xb8, 0xf4, 0xe0, 0x9a, 0x95, 0x18, 0x92, 0xd8, 0xc0, 0xb6, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x24, 0x44, 0x00, 0xd7, 0x84, 0x00, 0x00, 0x00, +}