1

Redstone フレームワークを使用して JSON 文字列を返すだけのClient Server Exampleのバリエーションを作成しています。3 つのルートがあります。

  • / => リスト全体または名前を取得する
  • /add/name => リストに「名前」を追加し、リストを取得します
  • /remove/name=> リストから「名前」を削除し、リストを取得します

ローカルでテストするとすべて正常に動作しますが、App Engine にデプロイすると、要素を gcloud db に追加しようとするとエラーが発生します。エラーは

例外: 1 個のエンティティを挿入しようとしましたが、0 個のエンティティを挿入したことを示す応答が返されたようです。パッケージ:appengine/src/api_impl/raw_datastore_v3_impl.dart 416:11 DatastoreV3RpcImpl.commit. dart:isolate _RawReceivePortImpl._handleMessage

この 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();
}
4

1 に答える 1

2

現在、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) 報告されたエラーは誤解を招くものであり、package:appengine で修正される予定です。

b) 近い将来、リクエスト ハンドラの外部で API 呼び出しを行うバックグラウンド タスク/タスクを許可する予定です。これは現時点ではありませんが、実装される予定です。

これが役立つことを願っています。

于 2014-11-26T13:08:34.393 に答える