feat: python grpc test client
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed

This commit is contained in:
Aravinth Manivannan 2023-12-27 19:48:51 +05:30
parent 6d90790e58
commit 4446cd83bd
Signed by: realaravinth
GPG key ID: F8F50389936984FF
5 changed files with 477 additions and 2 deletions

6
Makefile Normal file
View file

@ -0,0 +1,6 @@
python.gen:
. venv/bin/activate && cd dcache_py
python -m grpc_tools.protoc \
-I=./proto/dcache/ --python_out=dcache_py/ \
--pyi_out=dcache_py/ \
--grpc_python_out=dcache_py/ ./proto/dcache/dcache.proto

56
dcache_py/dcache_pb2.py Normal file
View file

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: dcache.proto
# Protobuf Python Version: 4.25.0
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x64\x63\x61\x63he.proto\x12\x06\x64\x63\x61\x63he\"?\n\x05Level\x12\x1a\n\x11visitor_threshold\x18\xad\x02 \x01(\r\x12\x1a\n\x11\x64ifficulty_factor\x18\xae\x02 \x01(\r\")\n\x07\x44\x65\x66\x65nse\x12\x1e\n\x06levels\x18\x91\x03 \x03(\x0b\x32\r.dcache.Level\"\\\n\x08MCaptcha\x12\x1a\n\x11visitor_threshold\x18\xf5\x03 \x01(\r\x12\x11\n\x08\x64uration\x18\xf6\x03 \x01(\x04\x12!\n\x07\x64\x65\x66\x65nse\x18\xf7\x03 \x01(\x0b\x32\x0f.dcache.Defense\">\n\nAddCaptcha\x12\x0b\n\x02id\x18\xd9\x04 \x01(\t\x12#\n\x08mcaptcha\x18\xda\x04 \x01(\x0b\x32\x10.dcache.MCaptcha\"2\n\rRenameCaptcha\x12\r\n\x04name\x18\xbd\x05 \x01(\t\x12\x12\n\trename_to\x18\xbe\x05 \x01(\t\"X\n\x08\x43\x61\x63hePoW\x12\x0f\n\x06string\x18\xa1\x06 \x01(\t\x12\x1a\n\x11\x64ifficulty_factor\x18\xa2\x06 \x01(\r\x12\x11\n\x08\x64uration\x18\xa3\x06 \x01(\x04\x12\x0c\n\x03key\x18\xa4\x06 \x01(\t\">\n\x0b\x43\x61\x63heResult\x12\x0e\n\x05token\x18\xb1\x06 \x01(\t\x12\x0c\n\x03key\x18\xb2\x06 \x01(\t\x12\x11\n\x08\x64uration\x18\xb3\x06 \x01(\x04\"%\n\x13\x44\x65leteCaptchaResult\x12\x0e\n\x05token\x18\xb5\x06 \x01(\t\"\xd4\x02\n\rDcacheRequest\x12\x14\n\nAddVisitor\x18\x01 \x01(\tH\x00\x12)\n\x0b\x61\x64\x64_captcha\x18\x02 \x01(\x0b\x32\x12.dcache.AddCaptchaH\x00\x12/\n\x0erename_captcha\x18\x03 \x01(\x0b\x32\x15.dcache.RenameCaptchaH\x00\x12\x18\n\x0eremove_captcha\x18\x04 \x01(\tH\x00\x12%\n\tcache_pow\x18\x05 \x01(\x0b\x32\x10.dcache.CachePoWH\x00\x12\x14\n\ndelete_pow\x18\x06 \x01(\tH\x00\x12+\n\x0c\x63\x61\x63he_result\x18\x07 \x01(\x0b\x32\x13.dcache.CacheResultH\x00\x12<\n\x15\x64\x65lete_captcha_result\x18\x08 \x01(\x0b\x32\x1b.dcache.DeleteCaptchaResultH\x00\x42\x0f\n\rDcacheRequest\"A\n\x10\x41\x64\x64VisitorResult\x12\x11\n\x08\x64uration\x18\x85\x07 \x01(\x04\x12\x1a\n\x11\x64ifficulty_factor\x18\x86\x07 \x01(\r\"S\n\x16OptionAddVisitorResult\x12.\n\x06result\x18\x8f\x07 \x01(\x0b\x32\x18.dcache.AddVisitorResultH\x00\x88\x01\x01\x42\t\n\x07_result\"x\n\x0e\x44\x63\x61\x63heResponse\x12\x43\n\x19option_add_visitor_result\x18\x01 \x01(\x0b\x32\x1e.dcache.OptionAddVisitorResultH\x00\x12\x0f\n\x05\x65mpty\x18\x02 \x01(\rH\x00\x42\x10\n\x0e\x44\x63\x61\x63heResponse\"\x1b\n\x0bRaftRequest\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"(\n\tRaftReply\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"#\n\x07Learner\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\t2\xcf\x02\n\rDcacheService\x12\x32\n\nAddLearner\x12\x0f.dcache.Learner\x1a\x11.dcache.RaftReply\"\x00\x12\x31\n\x05Write\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x33\n\x07\x46orward\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\"\x00\x12\x37\n\rAppendEntries\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\x12\x39\n\x0fInstallSnapshot\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReply\x12.\n\x04vote\x12\x13.dcache.RaftRequest\x1a\x11.dcache.RaftReplyb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dcache_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_globals['_LEVEL']._serialized_start=24
_globals['_LEVEL']._serialized_end=87
_globals['_DEFENSE']._serialized_start=89
_globals['_DEFENSE']._serialized_end=130
_globals['_MCAPTCHA']._serialized_start=132
_globals['_MCAPTCHA']._serialized_end=224
_globals['_ADDCAPTCHA']._serialized_start=226
_globals['_ADDCAPTCHA']._serialized_end=288
_globals['_RENAMECAPTCHA']._serialized_start=290
_globals['_RENAMECAPTCHA']._serialized_end=340
_globals['_CACHEPOW']._serialized_start=342
_globals['_CACHEPOW']._serialized_end=430
_globals['_CACHERESULT']._serialized_start=432
_globals['_CACHERESULT']._serialized_end=494
_globals['_DELETECAPTCHARESULT']._serialized_start=496
_globals['_DELETECAPTCHARESULT']._serialized_end=533
_globals['_DCACHEREQUEST']._serialized_start=536
_globals['_DCACHEREQUEST']._serialized_end=876
_globals['_ADDVISITORRESULT']._serialized_start=878
_globals['_ADDVISITORRESULT']._serialized_end=943
_globals['_OPTIONADDVISITORRESULT']._serialized_start=945
_globals['_OPTIONADDVISITORRESULT']._serialized_end=1028
_globals['_DCACHERESPONSE']._serialized_start=1030
_globals['_DCACHERESPONSE']._serialized_end=1150
_globals['_RAFTREQUEST']._serialized_start=1152
_globals['_RAFTREQUEST']._serialized_end=1179
_globals['_RAFTREPLY']._serialized_start=1181
_globals['_RAFTREPLY']._serialized_end=1221
_globals['_LEARNER']._serialized_start=1223
_globals['_LEARNER']._serialized_end=1258
_globals['_DCACHESERVICE']._serialized_start=1261
_globals['_DCACHESERVICE']._serialized_end=1596
# @@protoc_insertion_point(module_scope)

138
dcache_py/dcache_pb2.pyi Normal file
View file

@ -0,0 +1,138 @@
from google.protobuf.internal import containers as _containers
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
DESCRIPTOR: _descriptor.FileDescriptor
class Level(_message.Message):
__slots__ = ("visitor_threshold", "difficulty_factor")
VISITOR_THRESHOLD_FIELD_NUMBER: _ClassVar[int]
DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int]
visitor_threshold: int
difficulty_factor: int
def __init__(self, visitor_threshold: _Optional[int] = ..., difficulty_factor: _Optional[int] = ...) -> None: ...
class Defense(_message.Message):
__slots__ = ("levels",)
LEVELS_FIELD_NUMBER: _ClassVar[int]
levels: _containers.RepeatedCompositeFieldContainer[Level]
def __init__(self, levels: _Optional[_Iterable[_Union[Level, _Mapping]]] = ...) -> None: ...
class MCaptcha(_message.Message):
__slots__ = ("visitor_threshold", "duration", "defense")
VISITOR_THRESHOLD_FIELD_NUMBER: _ClassVar[int]
DURATION_FIELD_NUMBER: _ClassVar[int]
DEFENSE_FIELD_NUMBER: _ClassVar[int]
visitor_threshold: int
duration: int
defense: Defense
def __init__(self, visitor_threshold: _Optional[int] = ..., duration: _Optional[int] = ..., defense: _Optional[_Union[Defense, _Mapping]] = ...) -> None: ...
class AddCaptcha(_message.Message):
__slots__ = ("id", "mcaptcha")
ID_FIELD_NUMBER: _ClassVar[int]
MCAPTCHA_FIELD_NUMBER: _ClassVar[int]
id: str
mcaptcha: MCaptcha
def __init__(self, id: _Optional[str] = ..., mcaptcha: _Optional[_Union[MCaptcha, _Mapping]] = ...) -> None: ...
class RenameCaptcha(_message.Message):
__slots__ = ("name", "rename_to")
NAME_FIELD_NUMBER: _ClassVar[int]
RENAME_TO_FIELD_NUMBER: _ClassVar[int]
name: str
rename_to: str
def __init__(self, name: _Optional[str] = ..., rename_to: _Optional[str] = ...) -> None: ...
class CachePoW(_message.Message):
__slots__ = ("string", "difficulty_factor", "duration", "key")
STRING_FIELD_NUMBER: _ClassVar[int]
DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int]
DURATION_FIELD_NUMBER: _ClassVar[int]
KEY_FIELD_NUMBER: _ClassVar[int]
string: str
difficulty_factor: int
duration: int
key: str
def __init__(self, string: _Optional[str] = ..., difficulty_factor: _Optional[int] = ..., duration: _Optional[int] = ..., key: _Optional[str] = ...) -> None: ...
class CacheResult(_message.Message):
__slots__ = ("token", "key", "duration")
TOKEN_FIELD_NUMBER: _ClassVar[int]
KEY_FIELD_NUMBER: _ClassVar[int]
DURATION_FIELD_NUMBER: _ClassVar[int]
token: str
key: str
duration: int
def __init__(self, token: _Optional[str] = ..., key: _Optional[str] = ..., duration: _Optional[int] = ...) -> None: ...
class DeleteCaptchaResult(_message.Message):
__slots__ = ("token",)
TOKEN_FIELD_NUMBER: _ClassVar[int]
token: str
def __init__(self, token: _Optional[str] = ...) -> None: ...
class DcacheRequest(_message.Message):
__slots__ = ("AddVisitor", "add_captcha", "rename_captcha", "remove_captcha", "cache_pow", "delete_pow", "cache_result", "delete_captcha_result")
ADDVISITOR_FIELD_NUMBER: _ClassVar[int]
ADD_CAPTCHA_FIELD_NUMBER: _ClassVar[int]
RENAME_CAPTCHA_FIELD_NUMBER: _ClassVar[int]
REMOVE_CAPTCHA_FIELD_NUMBER: _ClassVar[int]
CACHE_POW_FIELD_NUMBER: _ClassVar[int]
DELETE_POW_FIELD_NUMBER: _ClassVar[int]
CACHE_RESULT_FIELD_NUMBER: _ClassVar[int]
DELETE_CAPTCHA_RESULT_FIELD_NUMBER: _ClassVar[int]
AddVisitor: str
add_captcha: AddCaptcha
rename_captcha: RenameCaptcha
remove_captcha: str
cache_pow: CachePoW
delete_pow: str
cache_result: CacheResult
delete_captcha_result: DeleteCaptchaResult
def __init__(self, AddVisitor: _Optional[str] = ..., add_captcha: _Optional[_Union[AddCaptcha, _Mapping]] = ..., rename_captcha: _Optional[_Union[RenameCaptcha, _Mapping]] = ..., remove_captcha: _Optional[str] = ..., cache_pow: _Optional[_Union[CachePoW, _Mapping]] = ..., delete_pow: _Optional[str] = ..., cache_result: _Optional[_Union[CacheResult, _Mapping]] = ..., delete_captcha_result: _Optional[_Union[DeleteCaptchaResult, _Mapping]] = ...) -> None: ...
class AddVisitorResult(_message.Message):
__slots__ = ("duration", "difficulty_factor")
DURATION_FIELD_NUMBER: _ClassVar[int]
DIFFICULTY_FACTOR_FIELD_NUMBER: _ClassVar[int]
duration: int
difficulty_factor: int
def __init__(self, duration: _Optional[int] = ..., difficulty_factor: _Optional[int] = ...) -> None: ...
class OptionAddVisitorResult(_message.Message):
__slots__ = ("result",)
RESULT_FIELD_NUMBER: _ClassVar[int]
result: AddVisitorResult
def __init__(self, result: _Optional[_Union[AddVisitorResult, _Mapping]] = ...) -> None: ...
class DcacheResponse(_message.Message):
__slots__ = ("option_add_visitor_result", "empty")
OPTION_ADD_VISITOR_RESULT_FIELD_NUMBER: _ClassVar[int]
EMPTY_FIELD_NUMBER: _ClassVar[int]
option_add_visitor_result: OptionAddVisitorResult
empty: int
def __init__(self, option_add_visitor_result: _Optional[_Union[OptionAddVisitorResult, _Mapping]] = ..., empty: _Optional[int] = ...) -> None: ...
class RaftRequest(_message.Message):
__slots__ = ("data",)
DATA_FIELD_NUMBER: _ClassVar[int]
data: str
def __init__(self, data: _Optional[str] = ...) -> None: ...
class RaftReply(_message.Message):
__slots__ = ("data", "error")
DATA_FIELD_NUMBER: _ClassVar[int]
ERROR_FIELD_NUMBER: _ClassVar[int]
data: str
error: str
def __init__(self, data: _Optional[str] = ..., error: _Optional[str] = ...) -> None: ...
class Learner(_message.Message):
__slots__ = ("id", "addr")
ID_FIELD_NUMBER: _ClassVar[int]
ADDR_FIELD_NUMBER: _ClassVar[int]
id: int
addr: str
def __init__(self, id: _Optional[int] = ..., addr: _Optional[str] = ...) -> None: ...

View file

@ -0,0 +1,234 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import dcache_py.dcache_pb2 as dcache__pb2
class DcacheServiceStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.AddLearner = channel.unary_unary(
'/dcache.DcacheService/AddLearner',
request_serializer=dcache__pb2.Learner.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.Write = channel.unary_unary(
'/dcache.DcacheService/Write',
request_serializer=dcache__pb2.RaftRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.Forward = channel.unary_unary(
'/dcache.DcacheService/Forward',
request_serializer=dcache__pb2.RaftRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.AppendEntries = channel.unary_unary(
'/dcache.DcacheService/AppendEntries',
request_serializer=dcache__pb2.RaftRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.InstallSnapshot = channel.unary_unary(
'/dcache.DcacheService/InstallSnapshot',
request_serializer=dcache__pb2.RaftRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
self.vote = channel.unary_unary(
'/dcache.DcacheService/vote',
request_serializer=dcache__pb2.RaftRequest.SerializeToString,
response_deserializer=dcache__pb2.RaftReply.FromString,
)
class DcacheServiceServicer(object):
"""Missing associated documentation comment in .proto file."""
def AddLearner(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Write(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Forward(self, request, context):
"""/ Forward a request to other
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def AppendEntries(self, request, context):
"""raft RPC
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def InstallSnapshot(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def vote(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_DcacheServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'AddLearner': grpc.unary_unary_rpc_method_handler(
servicer.AddLearner,
request_deserializer=dcache__pb2.Learner.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'Write': grpc.unary_unary_rpc_method_handler(
servicer.Write,
request_deserializer=dcache__pb2.RaftRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'Forward': grpc.unary_unary_rpc_method_handler(
servicer.Forward,
request_deserializer=dcache__pb2.RaftRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'AppendEntries': grpc.unary_unary_rpc_method_handler(
servicer.AppendEntries,
request_deserializer=dcache__pb2.RaftRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'InstallSnapshot': grpc.unary_unary_rpc_method_handler(
servicer.InstallSnapshot,
request_deserializer=dcache__pb2.RaftRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
'vote': grpc.unary_unary_rpc_method_handler(
servicer.vote,
request_deserializer=dcache__pb2.RaftRequest.FromString,
response_serializer=dcache__pb2.RaftReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'dcache.DcacheService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class DcacheService(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def AddLearner(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AddLearner',
dcache__pb2.Learner.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def Write(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/Write',
dcache__pb2.RaftRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def Forward(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/Forward',
dcache__pb2.RaftRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def AppendEntries(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/AppendEntries',
dcache__pb2.RaftRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def InstallSnapshot(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/InstallSnapshot',
dcache__pb2.RaftRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def vote(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/dcache.DcacheService/vote',
dcache__pb2.RaftRequest.SerializeToString,
dcache__pb2.RaftReply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

45
test.py
View file

@ -17,6 +17,12 @@
from pprint import pprint from pprint import pprint
import requests import requests
import grpc
import json
from dcache_py.dcache_pb2 import RaftRequest
from dcache_py.dcache_pb2_grpc import DcacheServiceStub
#import dcache_py.dcache_resources
def init(host: str): def init(host: str):
@ -96,6 +102,41 @@ def initialize_cluster():
if __name__ == "__main__":
add_vote("localhost:9002", captcha_id) def grpc_add_vote(stub: DcacheServiceStub, captcha_id: str):
msg = RaftRequest(data=json.dumps({"AddVisitor": captcha_id}))
resp = stub.Write(msg)
pprint(resp)
def grpc_add_captcha(stub: DcacheServiceStub, captcha_id: str):
params = {
"AddCaptcha": {
"id": captcha_id,
"mcaptcha": {
"visitor_threshold": 0,
"defense": {
"levels": [
{"visitor_threshold": 50, "difficulty_factor": 500},
{"visitor_threshold": 5000, "difficulty_factor": 50000},
],
"current_visitor_threshold": 0,
},
"duration": 30,
},
}
}
msg = RaftRequest(data = json.dumps(params))
resp = stub.Write(msg)
pprint(f"Captcha added {captcha_id}: {resp}")
def grpc_run():
with grpc.insecure_channel(host) as channel:
stub = DcacheServiceStub(channel)
grpc_add_captcha(stub, captcha_id)
if __name__ == "__main__":
grpc_run()
#add_vote("localhost:9002", captcha_id)