proto

Репозиторий содержит файлы для Protobuf (контрактов и описание сервисов) для автоматической генерации классов/структур под языки программирования поддерживание Protobuf

Глоссарий

  1. Контракт – в файле proto это message, это соглашение на объект/класс/структура
  2. Сервис – в файле proto это service, это соглашение по grpc сервису и его входащим/исходящим методам
  3. Метод сервиса – в файле proto это rpc, это соглашение по методу сервиса и его входащим/исходящим контрактам

Структура репозитория

  • draft – содержить прототипы/черновики файлов .proto
  • gen – содержит автоматически сгенерированные каталоги и файлы *.pb.go для подключения в качестве модуля в другие проекты на golang
  • rasapies – содержит файлы описание пакетов работы со службой ras
    • protocol/v1 – содержит контракты необходимые для работы с протоколом ras
    • messages/v1 – содержит контракты сообщений для работы с endpoint по протоколу ras
    • encoding – содержит вспомогательные опции контрактов/полей контрактов и файлов .proto для автоматической генерации encode/decode в бинарный протокол 1С. Для реализации автоматической генерации надо создать плагин для protoc
    • api/v1 – содержит контракты и сервисы ras

ЭТО СОГЛАШЕНИЕ, что сервис созданный для работы с ras (неважно на каком языке) будет работать согласно его контракту

ЭТО Позволяет автоматически создать заготовку клиента и сервера для любого языка

  • serializeapis – содержит файлы описание контрактов общих для платформы 1С
    • v8platform/serialize/v1 – содержит общие контракты версии 1
  • third_party – содержит файлы подключаемых стронних контрактов

Как использовать

Прежде всего необходимо понять следующее:

  1. protoc – компилятор для файлов .proto, но чтобы он работал надо устанавливать под каждый язык свой плагин Например, для golang – он называется protoc-gen-go

  2. buf – это приложение компилятор-плагин для .proto, protoc, которая компилирует файлы по заднной конфигурации

  3. Install bufon your machine

go install github.com/bufbuild/buf/cmd/buf # required
go install github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking
go install github.com/bufbuild/buf/cmd/protoc-gen-buf-lint
  1. Install protobuf & plugins

go install google.golang.org/protobuf/cmd/protoc-gen-go
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install github.com/srikrsna/protoc-gen-gotag
  1. Add to your project file buf.gen.yaml to generate *.pb.go

---
version: v1
managed:
  enabled: true
  go_package_prefix:
    default: github.com/your-name/repo-name/gen/go
    except:
      - buf.build/googleapis/googleapis
      - googleapies/google/api

plugins:
  - name: go
    out: ./gen/go
    opt: paths=source_relative
  - name: go-grpc
    out: ./gen/go
    opt: paths=source_relative,require_unimplemented_servers=false
  #  - name: grpc-gateway
  #    out: ./gen/go
  #    opt:
  #      - paths=source_relative
  #      - generate_unbound_methods=true
  #      - grpc_api_configuration=grpc-rest-bindings.yml
  - name: gotag
    out: .
    opt:
      - paths=source_relative
      - outdir=./gen/go
  1. Create file grpc-rest-bindings.yaml for generate grpc-gateway:

---
---
type: google.api.Service
config_version: 3

name: ras.api.v1
title: RAS API v1

apis:
  - name: ClustersService
  - mane: ClusterAdminService
  - mane: InfobasesService
http:
  rules:
    # Clusters
    - selector: ras.api.v1.ClustersService.Clusters
      get: '/clusters'
    - selector: ras.api.v1.ClustersService.GetCluster
      get: '/clusters/{cluster.id}'
    - selector: ras.api.v1.ClustersService.AddCluster
      post: '/clusters'
      body: '*'
    - selector: ras.api.v1.ClustersService.DeleteCluster
      delete: '/clusters/{cluster.id}'

    # Cluster admin
    - selector: ras.api.v1.ClusterAdminService.Admins
      get: '/clusters/{cluster.id}/admins'
      additional_bindings:
        - get: "/admins"
    - selector: ras.api.v1.ClusterAdminService.AddAdmin
      post: '/clusters/{cluster.id}/admins'
      body: 'admin_info'
      additional_bindings:
        - post: "/admins"
          body: 'admin_info'
    - selector: ras.api.v1.ClusterAdminService.DeleteAdmin
      delete: '/clusters/{cluster.id}/admins/{admin_name}'
      additional_bindings:
        - delete: "/admins/{admin_name}"

    # Infobases
    - selector: ras.api.v1.InfobasesService.Infobases
      get: '/infobases'
      additional_bindings:
        - get: '/clusters/{cluster.id}/infobases'
    - selector: ras.api.v1.InfobasesService.LookupInfobase
      get: "/infobases/lookup"
      additional_bindings:
        - get: '/clusters/{cluster.id}/infobases/lookup'
  1. Run generate command

buf generate https://github.com/v8platform/protos.git
  1. Code your client or server file
  • file for server Server/main.go

package main

import (
	"context"
	"fmt"
	"log"
	"net"

	// This import path is based on the name declaration in the go.mod,
	// and the gen/proto/go output location in the buf.gen.yaml.
	rasv1 "github.com/your-name/repo-name/gen/go/ras/api/v1"
	serializev1 "github.com/your-name/repo-name/gen/go/v8platform/protocol/v1"

	"google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	listenOn := "127.0.0.1:8080"
	listener, err := net.Listen("tcp", listenOn)
	if err != nil {
		return fmt.Errorf("failed to listen on %s: %w", listenOn, err)
	}

	server := grpc.NewServer()
	rasv1.RegisterClustersServiceServer(server, &rasClusterServiceServer{})
	log.Println("Listening on", listenOn)
	if err := server.Serve(listener); err != nil {
		return fmt.Errorf("failed to serve gRPC server: %w", err)
	}

	return nil
}

// petStoreServiceServer implements the PetStoreService API.
type rasClusterServiceServer struct {
	rasv1.UnimplementedClustersServiceServer
}

func (rasClusterServiceServer) Clusters(ctx context.Context, req *rasv1.GetClustersRequest) (*rasv1.GetClustersResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Clusters not implemented")
}
func (rasClusterServiceServer) GetCluster(ctx context.Context, req *rasv1.GetClusterRequest) (*serializev1.ClusterInfo, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetCluster not implemented")
}
func (rasClusterServiceServer) AddCluster(ctx context.Context, req *rasv1.AddClusterRequest) (*rasv1.AddClusterResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method AddCluster not implemented")
}
func (rasClusterServiceServer) DeleteCluster(ctx context.Context, req *rasv1.DeleteClusterRequest) (*emptypb.Empty, error) {
	return nil, status.Errorf(codes.Unimplemented, "method DeleteCluster not implemented")
}
  • file for client client/main.go

package main

import (
	"context"
	"fmt"
	"log"

	// This import path is based on the name declaration in the go.mod,
	// and the gen/proto/go output location in the buf.gen.yaml.
	rasv1 "github.com/your-name/repo-name/gen/go/ras/api/v1"
	"google.golang.org/grpc"
)

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}
func run() error {
	connectTo := "127.0.0.1:8080"
	conn, err := grpc.Dial(connectTo, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		return fmt.Errorf("failed to connect to ClustersService on %s: %w", connectTo, err)
	}
	log.Println("Connected to", connectTo)

	clusterService := rasv1.NewClustersServiceClient(conn)
	resp, err := clusterService.Clusters(context.Background(), &rasv1.GetClustersRequest{})
	if err != nil {
		return fmt.Errorf("failed to Clusters: %w", err)
	}

	log.Printf("Successfully Clusters %s", resp.String())
	return nil
}
  1. Yohooo run it. Take many profit

GitHub

https://github.com/v8platform/protos