尝试使用 Dart 将元素插入 App Engine 上的 gcloud DB 时出错



我正在制作客户端服务器示例的变体,该示例仅使用Redstone框架返回JSON字符串。它有3条路线:

  • / => 获取整个列表或名称
  • /add/name => 将"name"添加到列表中并获取列表
  • /remove/name => 从列表中删除"名称"并获取列表

当我在本地测试时,一切正常,但是,当我部署到 App Engine 时,尝试将元素添加到 gcloud 数据库时出现错误。错误是

异常:尝试插入 1 个实体,但响应似乎指示 我们插入了 0 个实体。 包装:appengine/src/api_impl/raw_datastore_v3_impl.dart 416:11 DatastoreV3RpcImpl.commit. dart:isolate _RawReceivePortImpl._句柄消息

您可以在此 URL 上实时测试错误 http://web3.arista-dev.appspot.com/add/my-name

删除似乎也不起作用,但不会产生错误。这是我的代码:

import 'dart:io';
import 'dart:async';
import 'package:shelf/shelf.dart' as shelf;
import 'package:redstone/server.dart' as app;
import 'package:restonetest/model.dart';
import 'package:gcloud/db.dart';
import 'package:appengine/appengine.dart';
Key get itemsRoot => context.services.db.emptyKey.append (ItemRoot, id: 1);
DatastoreDB db = context.services.db;
Future<List<Item>> queryItems ()
{
    var query = context.services.db.query (Item, ancestorKey: itemsRoot)
        ..order ('name');
    return query.run ().toList ();
}
Future<List<Item>> addItemToDB (Item item)
{
    return db.query(Item, ancestorKey: itemsRoot).run()
        .any((i) => i.name == item.name)
        .then((exists) 
        {
                return ! exists ? db.commit(inserts: [item]) : false;
        });
}
@app.Route("/")
helloWorld() => queryItems();
@app.Route('/add/:name')
addItem (String name)
{
    return addItemToDB (new Item.create (name, itemsRoot)).then ((_) 
    {
        print (name);    
        return helloWorld();
    });
}
@app.Route('/delete/:name')
deleteItem (String name) 
{
    var query = db.query (Item, ancestorKey: itemsRoot)..filter('name =', name);
    return query.run().toList().then((list) 
    { 
        var toDelete = list.map((i) => i.key).toList();
        return db.commit(deletes: toDelete);
    })
    .then((_) => helloWorld());
}
main() {
    app.setupConsoleLog();
    app.setUp();
    runAppEngine(app.handleRequest);
    //app.start();
}

目前,package:appengine 只允许在请求处理程序中调用 API 服务:

每个请求处理程序调用都将获得一组新的服务。这允许 package:appengine 为每个请求处理程序提供,例如不同的日志记录服务实例。这允许按请求对所有日志记录 API 调用进行分组。

在dart/package:appengine中实现这一点的方式是使用Zones。对于每个传入的请求,package:appengine 都会创建一个包含 API 服务的新区域,并在其中调用请求处理程序。然后,处理程序可以使用"context.services."进行API调用。

因此,上面发布的程序中的问题是 DatastoreDB 服务从第一个请求中缓存(全局字段被延迟初始化),并且可能不再适用于后续请求。

改变

DatastoreDB db = context.services.db;

DatastoreDB get db => context.services.db;

应该可以解决问题,因为每次从请求处理程序区域都会重新获取服务对象。

话虽如此:

a)错误被吞噬报告具有误导性,将在包:appengine中修复

b) 在不久的将来,我们将允许后台任务/在请求处理程序之外进行 API 调用的任务。这目前还缺少,但将实施。

我希望这有所帮助。

相关内容

最新更新