Google App Engine Api和Endpoints的版本控制

4

我遇到一些麻烦,无法找到处理应用程序中多个远程服务API版本的正确方式。

class MyService(Service):
   @endpoints.method(
        endpoints.ResourceContainer(
            something=protorpc.messages.StringField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_stuff(self, request):
        ... implement do_stuff ...

class MyBetterService(MyService):
    @endpoints.method(
        endpoints.ResourceContainer(
            some_other_name=protorpc.messages.StringField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_stuff(self, request):
        # ...other way of doing stuff
        return message_types.VoidMessage()

尝试制作库时出现以下错误: protorpc.remote.ServiceDefinitionError: 在MyBetterService服务的远程方法do_stuff上重载方法时,不要使用方法修饰符。
是否有覆盖下一个API版本中方法的方式?
重载的方法可能需要其他请求参数吗?
是否有可能在现有API中仅添加一个端点到不同版本?
1个回答

3

端点服务类是这样编写的,一旦您定义了一个公共接口方法,就不能在子类中更改它们。通常情况下,除非它是超类接口的确切超集,否则不应将新的API版本定义为子类。

如果新版本是超集,则可以使用重新定义接口方法,该方法将自动继承父方法的属性。例如:

class MyService(Service):
   @endpoints.method(
        endpoints.ResourceContainer(
            something=protorpc.messages.StringField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_stuff(self, request):
        ... implement do_stuff ...

class MyBetterService(MyService):
    def do_stuff(self, request):
        # ...other way of doing stuff
        return message_types.VoidMessage()

   @endpoints.method(
        endpoints.ResourceContainer(
            something=protorpc.messages.IntegerField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_more_stuff(self, request):
        ... implement do_more_stuff ...

do_stuff()的输入类型无法更改。

实际上,新的API版本应该像新的API一样对待,并具有独立的服务类定义。将API视为接口。虽然两个类不应共享具有公共API方法定义的基类,但这并不意味着两个类现在可以共享一组常规功能类。

当我构建服务时,即使我必须复制许多方法签名,我也会将API版本实现为单独的类。但是,在服务下面,我实现了一套对象系统,完全独立于接口和API消息类型执行相同的操作。这允许两个API版本共享实现的重要部分。

例如:

from mysystem import MyImplementation

class MyService(Service):
   @endpoints.method(
        endpoints.ResourceContainer(
            something=protorpc.messages.StringField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_stuff(self, request):
      MyImplementation.do_stuff(request.something)

class MyBetterService(Service):
   @endpoints.method(
        endpoints.ResourceContainer(
            something=protorpc.messages.IntegerField(1, required=True),
        ),
        message_types.VoidMessage,
    )
    def do_stuff(self, request):
      MyImplementation.do_stuff(self.lookup_string(request.something))

在这个模型中,我认为API负责在服务接口和实际底层系统之间传递信息,而不是实际的实现。
虽然为每个新的实现显式复制每个方法可能看起来很费力,但实际上它通常只占到你的整个服务应该做的工作的很小一部分。

在第二个例子中,应该有class MyBetterService(Service):。但我认为这是最好的解决方案。 - phoenix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接