DEVELOPMENT ENVIRONMENT

~liljamo/emerwen-proto

a2043b25fb13d913de476840ced88c024d301301 — Jonni Liljamo 6 days ago
feat: initial
A  => .envrc +1 -0
@@ 1,1 @@
use_flake

A  => .gitignore +3 -0
@@ 1,3 @@
/.direnv/

/.pre-commit-config.yaml

A  => flake.lock +125 -0
@@ 1,125 @@
{
  "nodes": {
    "flake-compat": {
      "flake": false,
      "locked": {
        "lastModified": 1696426674,
        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
        "owner": "edolstra",
        "repo": "flake-compat",
        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
        "type": "github"
      },
      "original": {
        "owner": "edolstra",
        "repo": "flake-compat",
        "type": "github"
      }
    },
    "flake-parts": {
      "inputs": {
        "nixpkgs-lib": [
          "nixpkgs"
        ]
      },
      "locked": {
        "lastModified": 1730504689,
        "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
        "owner": "hercules-ci",
        "repo": "flake-parts",
        "rev": "506278e768c2a08bec68eb62932193e341f55c90",
        "type": "github"
      },
      "original": {
        "owner": "hercules-ci",
        "repo": "flake-parts",
        "type": "github"
      }
    },
    "gitignore": {
      "inputs": {
        "nixpkgs": [
          "pre-commit-hooks",
          "nixpkgs"
        ]
      },
      "locked": {
        "lastModified": 1709087332,
        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
        "owner": "hercules-ci",
        "repo": "gitignore.nix",
        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
        "type": "github"
      },
      "original": {
        "owner": "hercules-ci",
        "repo": "gitignore.nix",
        "type": "github"
      }
    },
    "nixpkgs": {
      "locked": {
        "lastModified": 1731763621,
        "narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=",
        "owner": "nixos",
        "repo": "nixpkgs",
        "rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d",
        "type": "github"
      },
      "original": {
        "owner": "nixos",
        "ref": "nixpkgs-unstable",
        "repo": "nixpkgs",
        "type": "github"
      }
    },
    "nixpkgs-stable": {
      "locked": {
        "lastModified": 1730741070,
        "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
        "owner": "NixOS",
        "repo": "nixpkgs",
        "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
        "type": "github"
      },
      "original": {
        "owner": "NixOS",
        "ref": "nixos-24.05",
        "repo": "nixpkgs",
        "type": "github"
      }
    },
    "pre-commit-hooks": {
      "inputs": {
        "flake-compat": "flake-compat",
        "gitignore": "gitignore",
        "nixpkgs": [
          "nixpkgs"
        ],
        "nixpkgs-stable": "nixpkgs-stable"
      },
      "locked": {
        "lastModified": 1731363552,
        "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=",
        "owner": "cachix",
        "repo": "git-hooks.nix",
        "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0",
        "type": "github"
      },
      "original": {
        "owner": "cachix",
        "repo": "git-hooks.nix",
        "type": "github"
      }
    },
    "root": {
      "inputs": {
        "flake-parts": "flake-parts",
        "nixpkgs": "nixpkgs",
        "pre-commit-hooks": "pre-commit-hooks"
      }
    }
  },
  "root": "root",
  "version": 7
}

A  => flake.nix +64 -0
@@ 1,64 @@
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    flake-parts = {
      url = "github:hercules-ci/flake-parts";
      inputs.nixpkgs-lib.follows = "nixpkgs";
    };

    pre-commit-hooks = {
      url = "github:cachix/git-hooks.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs @ {
    self,
    nixpkgs,
    flake-parts,
    pre-commit-hooks,
    ...
  }:
    flake-parts.lib.mkFlake {inherit inputs;} {
      systems = ["x86_64-linux"];
      perSystem = {
        config,
        lib,
        pkgs,
        system,
        ...
      }: let
        libs = [];
      in {
        checks.pre-commit-check = pre-commit-hooks.lib.${system}.run {
          src = ./.;
          hooks = {
            # Nix formatting
            alejandra.enable = true;

            # Spell checking
            typos.enable = true;
          };
        };

        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs;
            [
              just

              protobuf
              protoc-gen-go
              protoc-gen-go-grpc
            ]
            ++ libs
            ++ [
              self.checks.${system}.pre-commit-check.enabledPackages
            ];
          LD_LIBRARY_PATH = lib.makeLibraryPath libs;
          shellHook = ''
            ${self.checks.${system}.pre-commit-check.shellHook}
          '';
        };
      };
    };
}

A  => go/shared/target.pb.go +344 -0
@@ 1,344 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.35.1
// 	protoc        v5.28.3
// source: shared/target.proto

package target

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type TargetState int32

const (
	TargetState_DOWN    TargetState = 0
	TargetState_UP      TargetState = 1
	TargetState_UNKNOWN TargetState = 2
)

// Enum value maps for TargetState.
var (
	TargetState_name = map[int32]string{
		0: "DOWN",
		1: "UP",
		2: "UNKNOWN",
	}
	TargetState_value = map[string]int32{
		"DOWN":    0,
		"UP":      1,
		"UNKNOWN": 2,
	}
)

func (x TargetState) Enum() *TargetState {
	p := new(TargetState)
	*p = x
	return p
}

func (x TargetState) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (TargetState) Descriptor() protoreflect.EnumDescriptor {
	return file_shared_target_proto_enumTypes[0].Descriptor()
}

func (TargetState) Type() protoreflect.EnumType {
	return &file_shared_target_proto_enumTypes[0]
}

func (x TargetState) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use TargetState.Descriptor instead.
func (TargetState) EnumDescriptor() ([]byte, []int) {
	return file_shared_target_proto_rawDescGZIP(), []int{0}
}

type Target struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Id       uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
	Addr     string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"`
	Interval uint32 `protobuf:"varint,3,opt,name=interval,proto3" json:"interval,omitempty"`
	// Types that are assignable to Method:
	//
	//	*Target_Ping
	//	*Target_Get
	Method isTarget_Method `protobuf_oneof:"method"`
}

func (x *Target) Reset() {
	*x = Target{}
	mi := &file_shared_target_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Target) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Target) ProtoMessage() {}

func (x *Target) ProtoReflect() protoreflect.Message {
	mi := &file_shared_target_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Target.ProtoReflect.Descriptor instead.
func (*Target) Descriptor() ([]byte, []int) {
	return file_shared_target_proto_rawDescGZIP(), []int{0}
}

func (x *Target) GetId() uint32 {
	if x != nil {
		return x.Id
	}
	return 0
}

func (x *Target) GetAddr() string {
	if x != nil {
		return x.Addr
	}
	return ""
}

func (x *Target) GetInterval() uint32 {
	if x != nil {
		return x.Interval
	}
	return 0
}

func (m *Target) GetMethod() isTarget_Method {
	if m != nil {
		return m.Method
	}
	return nil
}

func (x *Target) GetPing() *Target_MethodPing {
	if x, ok := x.GetMethod().(*Target_Ping); ok {
		return x.Ping
	}
	return nil
}

func (x *Target) GetGet() *Target_MethodGET {
	if x, ok := x.GetMethod().(*Target_Get); ok {
		return x.Get
	}
	return nil
}

type isTarget_Method interface {
	isTarget_Method()
}

type Target_Ping struct {
	Ping *Target_MethodPing `protobuf:"bytes,4,opt,name=ping,proto3,oneof"`
}

type Target_Get struct {
	Get *Target_MethodGET `protobuf:"bytes,5,opt,name=get,proto3,oneof"`
}

func (*Target_Ping) isTarget_Method() {}

func (*Target_Get) isTarget_Method() {}

type Target_MethodPing struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
}

func (x *Target_MethodPing) Reset() {
	*x = Target_MethodPing{}
	mi := &file_shared_target_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Target_MethodPing) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Target_MethodPing) ProtoMessage() {}

func (x *Target_MethodPing) ProtoReflect() protoreflect.Message {
	mi := &file_shared_target_proto_msgTypes[1]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Target_MethodPing.ProtoReflect.Descriptor instead.
func (*Target_MethodPing) Descriptor() ([]byte, []int) {
	return file_shared_target_proto_rawDescGZIP(), []int{0, 0}
}

type Target_MethodGET struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	OkCodes []uint32 `protobuf:"varint,1,rep,packed,name=ok_codes,json=okCodes,proto3" json:"ok_codes,omitempty"`
}

func (x *Target_MethodGET) Reset() {
	*x = Target_MethodGET{}
	mi := &file_shared_target_proto_msgTypes[2]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Target_MethodGET) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Target_MethodGET) ProtoMessage() {}

func (x *Target_MethodGET) ProtoReflect() protoreflect.Message {
	mi := &file_shared_target_proto_msgTypes[2]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Target_MethodGET.ProtoReflect.Descriptor instead.
func (*Target_MethodGET) Descriptor() ([]byte, []int) {
	return file_shared_target_proto_rawDescGZIP(), []int{0, 1}
}

func (x *Target_MethodGET) GetOkCodes() []uint32 {
	if x != nil {
		return x.OkCodes
	}
	return nil
}

var File_shared_target_proto protoreflect.FileDescriptor

var file_shared_target_proto_rawDesc = []byte{
	0x0a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x73,
	0x68, 0x61, 0x72, 0x65, 0x64, 0x22, 0xf7, 0x01, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64,
	0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
	0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
	0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
	0x12, 0x37, 0x0a, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
	0x2e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e,
	0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x69, 0x6e,
	0x67, 0x48, 0x00, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x03, 0x67, 0x65, 0x74,
	0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e,
	0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x4d,
	0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x45, 0x54, 0x48, 0x00, 0x52, 0x03, 0x67, 0x65, 0x74, 0x1a,
	0x0c, 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x69, 0x6e, 0x67, 0x1a, 0x26, 0x0a,
	0x09, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x45, 0x54, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6b,
	0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x6f, 0x6b,
	0x43, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2a,
	0x2c, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08,
	0x0a, 0x04, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x55, 0x50, 0x10, 0x01,
	0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x02, 0x42, 0x30, 0x5a,
	0x2e, 0x67, 0x69, 0x74, 0x2e, 0x73, 0x72, 0x63, 0x2e, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x7e,
	0x6c, 0x69, 0x6c, 0x6a, 0x61, 0x6d, 0x6f, 0x2f, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2d,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x62,
	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_shared_target_proto_rawDescOnce sync.Once
	file_shared_target_proto_rawDescData = file_shared_target_proto_rawDesc
)

func file_shared_target_proto_rawDescGZIP() []byte {
	file_shared_target_proto_rawDescOnce.Do(func() {
		file_shared_target_proto_rawDescData = protoimpl.X.CompressGZIP(file_shared_target_proto_rawDescData)
	})
	return file_shared_target_proto_rawDescData
}

var file_shared_target_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_shared_target_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_shared_target_proto_goTypes = []any{
	(TargetState)(0),          // 0: emerwen.shared.TargetState
	(*Target)(nil),            // 1: emerwen.shared.Target
	(*Target_MethodPing)(nil), // 2: emerwen.shared.Target.MethodPing
	(*Target_MethodGET)(nil),  // 3: emerwen.shared.Target.MethodGET
}
var file_shared_target_proto_depIdxs = []int32{
	2, // 0: emerwen.shared.Target.ping:type_name -> emerwen.shared.Target.MethodPing
	3, // 1: emerwen.shared.Target.get:type_name -> emerwen.shared.Target.MethodGET
	2, // [2:2] is the sub-list for method output_type
	2, // [2:2] is the sub-list for method input_type
	2, // [2:2] is the sub-list for extension type_name
	2, // [2:2] is the sub-list for extension extendee
	0, // [0:2] is the sub-list for field type_name
}

func init() { file_shared_target_proto_init() }
func file_shared_target_proto_init() {
	if File_shared_target_proto != nil {
		return
	}
	file_shared_target_proto_msgTypes[0].OneofWrappers = []any{
		(*Target_Ping)(nil),
		(*Target_Get)(nil),
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_shared_target_proto_rawDesc,
			NumEnums:      1,
			NumMessages:   3,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_shared_target_proto_goTypes,
		DependencyIndexes: file_shared_target_proto_depIdxs,
		EnumInfos:         file_shared_target_proto_enumTypes,
		MessageInfos:      file_shared_target_proto_msgTypes,
	}.Build()
	File_shared_target_proto = out.File
	file_shared_target_proto_rawDesc = nil
	file_shared_target_proto_goTypes = nil
	file_shared_target_proto_depIdxs = nil
}

A  => go/shared/worker.pb.go +153 -0
@@ 1,153 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.35.1
// 	protoc        v5.28.3
// source: shared/worker.proto

package worker

import (
	target "git.src.quest/~liljamo/emerwen-proto/go/target"
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type Worker struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Id        uint32           `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
	AuthToken string           `protobuf:"bytes,2,opt,name=auth_token,json=authToken,proto3" json:"auth_token,omitempty"`
	Targets   []*target.Target `protobuf:"bytes,3,rep,name=targets,proto3" json:"targets,omitempty"`
}

func (x *Worker) Reset() {
	*x = Worker{}
	mi := &file_shared_worker_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Worker) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Worker) ProtoMessage() {}

func (x *Worker) ProtoReflect() protoreflect.Message {
	mi := &file_shared_worker_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Worker.ProtoReflect.Descriptor instead.
func (*Worker) Descriptor() ([]byte, []int) {
	return file_shared_worker_proto_rawDescGZIP(), []int{0}
}

func (x *Worker) GetId() uint32 {
	if x != nil {
		return x.Id
	}
	return 0
}

func (x *Worker) GetAuthToken() string {
	if x != nil {
		return x.AuthToken
	}
	return ""
}

func (x *Worker) GetTargets() []*target.Target {
	if x != nil {
		return x.Targets
	}
	return nil
}

var File_shared_worker_proto protoreflect.FileDescriptor

var file_shared_worker_proto_rawDesc = []byte{
	0x0a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x73,
	0x68, 0x61, 0x72, 0x65, 0x64, 0x1a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x74, 0x61,
	0x72, 0x67, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x69, 0x0a, 0x06, 0x57, 0x6f,
	0x72, 0x6b, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
	0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b,
	0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f,
	0x6b, 0x65, 0x6e, 0x12, 0x30, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x03,
	0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x73,
	0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61,
	0x72, 0x67, 0x65, 0x74, 0x73, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x2e, 0x73, 0x72, 0x63,
	0x2e, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x7e, 0x6c, 0x69, 0x6c, 0x6a, 0x61, 0x6d, 0x6f, 0x2f,
	0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f,
	0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_shared_worker_proto_rawDescOnce sync.Once
	file_shared_worker_proto_rawDescData = file_shared_worker_proto_rawDesc
)

func file_shared_worker_proto_rawDescGZIP() []byte {
	file_shared_worker_proto_rawDescOnce.Do(func() {
		file_shared_worker_proto_rawDescData = protoimpl.X.CompressGZIP(file_shared_worker_proto_rawDescData)
	})
	return file_shared_worker_proto_rawDescData
}

var file_shared_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_shared_worker_proto_goTypes = []any{
	(*Worker)(nil),        // 0: emerwen.shared.Worker
	(*target.Target)(nil), // 1: emerwen.shared.Target
}
var file_shared_worker_proto_depIdxs = []int32{
	1, // 0: emerwen.shared.Worker.targets:type_name -> emerwen.shared.Target
	1, // [1:1] is the sub-list for method output_type
	1, // [1:1] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
}

func init() { file_shared_worker_proto_init() }
func file_shared_worker_proto_init() {
	if File_shared_worker_proto != nil {
		return
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_shared_worker_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_shared_worker_proto_goTypes,
		DependencyIndexes: file_shared_worker_proto_depIdxs,
		MessageInfos:      file_shared_worker_proto_msgTypes,
	}.Build()
	File_shared_worker_proto = out.File
	file_shared_worker_proto_rawDesc = nil
	file_shared_worker_proto_goTypes = nil
	file_shared_worker_proto_depIdxs = nil
}

A  => go/webtomaster.pb.go +146 -0
@@ 1,146 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.35.1
// 	protoc        v5.28.3
// source: webtomaster.proto

package _go

import (
	worker "git.src.quest/~liljamo/emerwen-proto/go/worker"
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type WorkersResponse struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Workers []*worker.Worker `protobuf:"bytes,1,rep,name=workers,proto3" json:"workers,omitempty"`
}

func (x *WorkersResponse) Reset() {
	*x = WorkersResponse{}
	mi := &file_webtomaster_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *WorkersResponse) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*WorkersResponse) ProtoMessage() {}

func (x *WorkersResponse) ProtoReflect() protoreflect.Message {
	mi := &file_webtomaster_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use WorkersResponse.ProtoReflect.Descriptor instead.
func (*WorkersResponse) Descriptor() ([]byte, []int) {
	return file_webtomaster_proto_rawDescGZIP(), []int{0}
}

func (x *WorkersResponse) GetWorkers() []*worker.Worker {
	if x != nil {
		return x.Workers
	}
	return nil
}

var File_webtomaster_proto protoreflect.FileDescriptor

var file_webtomaster_proto_rawDesc = []byte{
	0x0a, 0x11, 0x77, 0x65, 0x62, 0x74, 0x6f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72,
	0x6f, 0x74, 0x6f, 0x12, 0x13, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x77, 0x65, 0x62,
	0x74, 0x6f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x77, 0x6f,
	0x72, 0x6b, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x0f, 0x57, 0x6f,
	0x72, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a,
	0x07, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
	0x2e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e,
	0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x32,
	0x59, 0x0a, 0x0b, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x4a,
	0x0a, 0x0a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67,
	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
	0x6d, 0x70, 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2e, 0x77,
	0x65, 0x62, 0x74, 0x6f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65,
	0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69,
	0x74, 0x2e, 0x73, 0x72, 0x63, 0x2e, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x7e, 0x6c, 0x69, 0x6c,
	0x6a, 0x61, 0x6d, 0x6f, 0x2f, 0x65, 0x6d, 0x65, 0x72, 0x77, 0x65, 0x6e, 0x2d, 0x70, 0x72, 0x6f,
	0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_webtomaster_proto_rawDescOnce sync.Once
	file_webtomaster_proto_rawDescData = file_webtomaster_proto_rawDesc
)

func file_webtomaster_proto_rawDescGZIP() []byte {
	file_webtomaster_proto_rawDescOnce.Do(func() {
		file_webtomaster_proto_rawDescData = protoimpl.X.CompressGZIP(file_webtomaster_proto_rawDescData)
	})
	return file_webtomaster_proto_rawDescData
}

var file_webtomaster_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_webtomaster_proto_goTypes = []any{
	(*WorkersResponse)(nil), // 0: emerwen.webtomaster.WorkersResponse
	(*worker.Worker)(nil),   // 1: emerwen.shared.Worker
	(*emptypb.Empty)(nil),   // 2: google.protobuf.Empty
}
var file_webtomaster_proto_depIdxs = []int32{
	1, // 0: emerwen.webtomaster.WorkersResponse.workers:type_name -> emerwen.shared.Worker
	2, // 1: emerwen.webtomaster.WebToMaster.GetWorkers:input_type -> google.protobuf.Empty
	0, // 2: emerwen.webtomaster.WebToMaster.GetWorkers:output_type -> emerwen.webtomaster.WorkersResponse
	2, // [2:3] is the sub-list for method output_type
	1, // [1:2] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
}

func init() { file_webtomaster_proto_init() }
func file_webtomaster_proto_init() {
	if File_webtomaster_proto != nil {
		return
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_webtomaster_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   1,
		},
		GoTypes:           file_webtomaster_proto_goTypes,
		DependencyIndexes: file_webtomaster_proto_depIdxs,
		MessageInfos:      file_webtomaster_proto_msgTypes,
	}.Build()
	File_webtomaster_proto = out.File
	file_webtomaster_proto_rawDesc = nil
	file_webtomaster_proto_goTypes = nil
	file_webtomaster_proto_depIdxs = nil
}

A  => go/webtomaster_grpc.pb.go +110 -0
@@ 1,110 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc             v5.28.3
// source: webtomaster.proto

package _go

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

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7

const (
	WebToMaster_GetWorkers_FullMethodName = "/emerwen.webtomaster.WebToMaster/GetWorkers"
)

// WebToMasterClient is the client API for WebToMaster service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type WebToMasterClient interface {
	GetWorkers(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*WorkersResponse, error)
}

type webToMasterClient struct {
	cc grpc.ClientConnInterface
}

func NewWebToMasterClient(cc grpc.ClientConnInterface) WebToMasterClient {
	return &webToMasterClient{cc}
}

func (c *webToMasterClient) GetWorkers(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*WorkersResponse, error) {
	out := new(WorkersResponse)
	err := c.cc.Invoke(ctx, WebToMaster_GetWorkers_FullMethodName, in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// WebToMasterServer is the server API for WebToMaster service.
// All implementations must embed UnimplementedWebToMasterServer
// for forward compatibility
type WebToMasterServer interface {
	GetWorkers(context.Context, *emptypb.Empty) (*WorkersResponse, error)
	mustEmbedUnimplementedWebToMasterServer()
}

// UnimplementedWebToMasterServer must be embedded to have forward compatible implementations.
type UnimplementedWebToMasterServer struct {
}

func (UnimplementedWebToMasterServer) GetWorkers(context.Context, *emptypb.Empty) (*WorkersResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetWorkers not implemented")
}
func (UnimplementedWebToMasterServer) mustEmbedUnimplementedWebToMasterServer() {}

// UnsafeWebToMasterServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to WebToMasterServer will
// result in compilation errors.
type UnsafeWebToMasterServer interface {
	mustEmbedUnimplementedWebToMasterServer()
}

func RegisterWebToMasterServer(s grpc.ServiceRegistrar, srv WebToMasterServer) {
	s.RegisterService(&WebToMaster_ServiceDesc, srv)
}

func _WebToMaster_GetWorkers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(emptypb.Empty)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(WebToMasterServer).GetWorkers(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: WebToMaster_GetWorkers_FullMethodName,
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(WebToMasterServer).GetWorkers(ctx, req.(*emptypb.Empty))
	}
	return interceptor(ctx, in, info, handler)
}

// WebToMaster_ServiceDesc is the grpc.ServiceDesc for WebToMaster service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var WebToMaster_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "emerwen.webtomaster.WebToMaster",
	HandlerType: (*WebToMasterServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "GetWorkers",
			Handler:    _WebToMaster_GetWorkers_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "webtomaster.proto",
}

A  => justfile +8 -0
@@ 1,8 @@
_default:
    just --list

compile-protos-go:
    protoc --go_out=go --go_opt=paths=source_relative \
        --go-grpc_out=go --go-grpc_opt=paths=source_relative \
        --proto_path=proto \
        proto/webtomaster.proto proto/shared/target.proto proto/shared/worker.proto

A  => proto/shared/target.proto +25 -0
@@ 1,25 @@
syntax = "proto3";
package emerwen.shared;

option go_package = "git.src.quest/~liljamo/emerwen-proto/go/target";

message Target {
    uint32 id = 1;
    string addr = 2;
    uint32 interval = 3;
    oneof method {
        MethodPing ping = 4;
        MethodGET get = 5;
    }

    message MethodPing {}
    message MethodGET {
        repeated uint32 ok_codes = 1;
    }
}

enum TargetState {
    DOWN = 0;
    UP = 1;
    UNKNOWN = 2;
}

A  => proto/shared/worker.proto +12 -0
@@ 1,12 @@
syntax = "proto3";
package emerwen.shared;

option go_package = "git.src.quest/~liljamo/emerwen-proto/go/worker";

import "shared/target.proto";

message Worker {
    uint32 id = 1;
    string auth_token = 2;
    repeated shared.Target targets = 3;
}

A  => proto/webtomaster.proto +15 -0
@@ 1,15 @@
syntax = "proto3";
package emerwen.webtomaster;

option go_package = "git.src.quest/~liljamo/emerwen-proto/go";

import "google/protobuf/empty.proto";
import "shared/worker.proto";

service WebToMaster {
    rpc GetWorkers (google.protobuf.Empty) returns (WorkersResponse);
}

message WorkersResponse {
    repeated shared.Worker workers = 1;
}

A  => proto/workertomaster.proto +19 -0
@@ 1,19 @@
syntax = "proto3";
package emerwen.workertomaster;

import "google/protobuf/empty.proto";
import "shared/target.proto";

service WorkerToMaster {
    rpc GetTargets (google.protobuf.Empty) returns (TargetsResponse);
    rpc SetTargetState (SetTargetStateRequest) returns (google.protobuf.Empty);
}

message TargetsResponse {
    repeated shared.Target targets = 1;
}

message SetTargetStateRequest {
    uint32 id = 1;
    shared.TargetState state = 2;
}