Запрос Python gRPC периодически отсутствует
Я использую gRPC в python с django и django-grpc-framework.
Когда я запускаю unittest, в моем models.py есть кусок кода, который создает странную проблему: я запрашиваю три gRPC-запроса, но только один достигает серверной стороны.
Подробности проблемы
Чтобы упростить проблему, следующий код объясняет ситуацию:
class MyModel(models.Model):
def some_method(self):
for stub in [stub1, stub2, stub3]:
resp = stub.RetractObject(base_pb2.RetractObjectRequest(
app_label='...',
object_type='...',
object_id='...',
exchange_id='...',
remark='...',
date_record='...',
))
Здесь метод some_method срабатывает в функции unittest django.test.TestCase
, в то время как gRPC подключается к внешнему запущенному экземпляру сервера.
А соответствующие .proto
файлы выглядят следующим образом:
// base.proto
// ...
message CreditRecord {
int64 id = 1;
string username = 2;
string app_label = 3;
string flag = 4;
string object_type = 5;
int64 object_id = 6;
int64 amount = 7;
int64 balance = 8;
string remark = 9;
string date_record = 10;
string exchange_id = 11;
int64 retract_ref = 12;
}
message RetractObjectRequest {
string app_label = 1;
string object_type = 2;
int64 object_id = 3;
string exchange_id = 4;
string remark = 5;
string date_record = 6;
}
// ...
// stub1 - stub3 has the similar structure below
syntax = "proto3";
package mjtest.growth;
import "mjtest/growth/base.proto";
service CreditController {
// ...
rpc RetractObject (RetractObjectRequest) returns (stream CreditRecord) {}
}
А код на стороне сервера выглядит примерно так (с использованием django-grpc-framework):
# services.py
class GenericCreditService(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericService):
def RetractObject(self, request: base_pb2.RetractObjectRequest, context):
print('Request reached!', request)
# ...
records = model_class.retract_object(...)
# Here, records has aready return a list, not a iterator.
for rec in records:
yield self.serializer_class(rec).message
Итак, когда я запускаю unittest, сторона клиента вызывает ТРИ раза, чтобы запросить RetractObject
gRPC-метод.
Но только ОДИН раз, когда Request reached!
был напечатан.
Попытка №1: добавление sleep(0.5)
Я предполагаю, что есть какая-то проблема на стороне клиента, и я добавляю sleep(0.5)
после каждого запроса.
class MyModel(models.Model):
def some_method(self):
for stub in [stub1, stub2, stub3]:
resp = stub.RetractObject(base_pb2.RetractObjectRequest(...))
sleep(0.5)
Тогда все три запроса достигают!
Попытка №2: обход ответа в явном виде.
Я предполагаю, что ответ потока без потребляемого может вызвать проблему, поэтому я передаю ответ в список явно.
class MyModel(models.Model):
def some_method(self):
for stub in [stub1, stub2, stub3]:
resp = stub.RetractObject(base_pb2.RetractObjectRequest(...))
list(resp)
Тогда все три запроса достигают!
Проблема настолько странная, и ни один из способов, которые я запрашиваю, не выдает ошибку.
Может ли кто-нибудь помочь?