1
0
Fork 0

added optional `ttl` attribute to specify result cursor expiration for HTTP API method `POST /_api/cursor`

The `ttl` attribute can be used to prevent cursor results from timing out too early.
This commit is contained in:
Jan Steemann 2014-07-21 15:48:43 +02:00
parent 472240948a
commit 712358d069
7 changed files with 222 additions and 79 deletions

View File

@ -1,11 +1,16 @@
v2.2.1 (XXXX-XX-XX)
-------------------
* issue #947 Foxx applicationContext missing some properties
* added optional `ttl` attribute to specify result cursor expiration for HTTP API method
`POST /_api/cursor`
The `ttl` attribute can be used to prevent cursor results from timing out too early.
* issue #947: Foxx applicationContext missing some properties
* (reported by Christian Neubauer):
The problem was that in googles V8, signed and unsignet chars are not always declared cleanly.
The problem was that in Google's V8, signed and unsigned chars are not always declared cleanly.
so we need to force v8 to compile with forced signed chars which is done by the Flag:
-fsigned-char
at least it is enough to follow the instructions of compiling arango on rasperry

View File

@ -288,7 +288,7 @@ describe ArangoDB do
doc.parsed_response['id'].should be_nil
end
it "deleting an invalid cursor" do
it "deleting an invalid cursor" do
cmd = api
cmd = api + "/999999" # we assume this cursor id is invalid
doc = ArangoDB.log_delete("#{prefix}-delete", cmd)
@ -300,6 +300,118 @@ describe ArangoDB do
doc.parsed_response['code'].should eq(404)
doc.parsed_response['id'].should be_nil
end
it "creates a cursor that will expire" do
cmd = api
body = "{ \"query\" : \"FOR u IN #{@cn} LIMIT 5 RETURN u.n\", \"count\" : true, \"batchSize\" : 1, \"ttl\" : 4 }"
doc = ArangoDB.log_post("#{prefix}-create-ttl", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 1
id = doc.parsed_response['id']
cmd = api + "/#{id}"
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 1
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 15 # this should delete the cursor on the server
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['errorNum'].should eq(1600)
doc.parsed_response['code'].should eq(404)
end
it "creates a cursor that will not expire" do
cmd = api
body = "{ \"query\" : \"FOR u IN #{@cn} LIMIT 5 RETURN u.n\", \"count\" : true, \"batchSize\" : 1, \"ttl\" : 60 }"
doc = ArangoDB.log_post("#{prefix}-create-ttl", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 1
id = doc.parsed_response['id']
cmd = api + "/#{id}"
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should be_kind_of(String)
doc.parsed_response['id'].should match(@reId)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 1
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json; charset=utf-8")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
sleep 5 # this should not delete the cursor on the server
doc = ArangoDB.log_put("#{prefix}-create-ttl", cmd)
doc.code.should eq(200)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['id'].should eq(id)
doc.parsed_response['hasMore'].should eq(true)
doc.parsed_response['count'].should eq(5)
doc.parsed_response['result'].length.should eq(1)
end
end
################################################################################

View File

@ -3486,9 +3486,10 @@ static v8::Handle<v8::Value> ExecuteQueryNativeAhuacatl (TRI_aql_context_t* cont
static v8::Handle<v8::Value> ExecuteQueryCursorAhuacatl (TRI_vocbase_t* const vocbase,
TRI_aql_context_t* const context,
const TRI_json_t* const parameters,
const bool doCount,
const uint32_t batchSize) {
TRI_json_t const* parameters,
bool doCount,
uint32_t batchSize,
double cursorTtl) {
v8::HandleScope scope;
v8::TryCatch tryCatch;
@ -3499,7 +3500,7 @@ static v8::Handle<v8::Value> ExecuteQueryCursorAhuacatl (TRI_vocbase_t* const vo
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(result);
@ -3536,35 +3537,35 @@ static v8::Handle<v8::Value> ExecuteQueryCursorAhuacatl (TRI_vocbase_t* const vo
// transform the result into JSON first
TRI_json_t* json = TRI_ObjectToJson(docs);
if (json == 0) {
if (json == nullptr) {
TRI_V8_EXCEPTION_MEMORY(scope);
}
TRI_general_cursor_result_t* cursorResult = TRI_CreateResultAql(json);
if (cursorResult == 0) {
if (cursorResult == nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
TRI_V8_EXCEPTION_MEMORY(scope);
}
// extra return values
TRI_json_t* extra = 0;
TRI_json_t* extra = nullptr;
if (resultObject->Has(TRI_V8_SYMBOL("extra"))) {
extra = TRI_ObjectToJson(resultObject->Get(TRI_V8_SYMBOL("extra")));
}
TRI_general_cursor_t* cursor = TRI_CreateGeneralCursor(vocbase, cursorResult, doCount, batchSize, extra);
TRI_general_cursor_t* cursor = TRI_CreateGeneralCursor(vocbase, cursorResult, doCount, batchSize, cursorTtl, extra);
if (cursor == 0) {
if (cursor == nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursorResult);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
if (extra != 0) {
if (extra != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, extra);
}
TRI_V8_EXCEPTION_MEMORY(scope);
}
TRI_ASSERT(cursor != 0);
TRI_ASSERT(cursor != nullptr);
v8::Handle<v8::Value> cursorObject = WrapGeneralCursor(cursor);
@ -4317,12 +4318,12 @@ static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
if (vocbase == nullptr) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
if (argv.Length() < 1) {
TRI_V8_EXCEPTION_USAGE(scope, "CREATE_CURSOR(<list>, <doCount>, <batchSize>)");
TRI_V8_EXCEPTION_USAGE(scope, "CREATE_CURSOR(<list>, <doCount>, <batchSize>, <ttl>)");
}
if (! argv[0]->IsArray()) {
@ -4333,7 +4334,7 @@ static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(argv[0]);
TRI_json_t* json = TRI_ObjectToJson(array);
if (json == 0) {
if (json == nullptr) {
TRI_V8_TYPE_ERROR(scope, "cannot convert <list> to JSON");
}
@ -4355,14 +4356,23 @@ static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
}
}
double ttl = 0.0;
if (argv.Length() >= 4) {
ttl = TRI_ObjectToDouble(argv[3]);
}
if (ttl <= 0.0) {
ttl = 30.0; // default ttl
}
// create a cursor
TRI_general_cursor_t* cursor = 0;
TRI_general_cursor_t* cursor = nullptr;
TRI_general_cursor_result_t* cursorResult = TRI_CreateResultAql(json);
if (cursorResult != 0) {
cursor = TRI_CreateGeneralCursor(vocbase, cursorResult, doCount, batchSize, 0);
if (cursorResult != nullptr) {
cursor = TRI_CreateGeneralCursor(vocbase, cursorResult, doCount, batchSize, ttl, 0);
if (cursor == 0) {
if (cursor == nullptr) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursorResult);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
}
@ -4371,7 +4381,7 @@ static v8::Handle<v8::Value> JS_CreateCursor (v8::Arguments const& argv) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
}
if (cursor == 0) {
if (cursor == nullptr) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot create cursor");
}
@ -4517,7 +4527,7 @@ static v8::Handle<v8::Value> JS_PersistGeneralCursor (v8::Arguments const& argv)
TRI_V8_EXCEPTION_USAGE(scope, "persist()");
}
TRI_PersistGeneralCursor(UnwrapGeneralCursor(argv.Holder()), 30.0);
TRI_PersistGeneralCursor(UnwrapGeneralCursor(argv.Holder()));
return scope.Close(v8::True());
}
@ -5370,6 +5380,9 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
// maximum number of results to return at once
uint32_t batchSize = UINT32_MAX;
// ttl for cursor
double ttl = 0.0;
if (argc > 2 && argv[2]->IsObject()) {
// treat the argument as an object from now on
@ -5386,12 +5399,21 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
batchSize = (uint32_t) maxValue;
}
}
if (options->Has(TRI_V8_SYMBOL("ttl"))) {
ttl = TRI_ObjectToDouble(options->Get(TRI_V8_SYMBOL("ttl")));
}
}
if (ttl <= 0.0) {
// default ttl
ttl = 30.0;
}
// user options
// -------------------------------------------------
TRI_json_t* userOptions = 0;
TRI_json_t* userOptions = nullptr;
if (argc > 3 && argv[3]->IsObject()) {
// treat the argument as an object from now on
v8::Handle<v8::Object> options = v8::Handle<v8::Object>::Cast(argv[3]);
@ -5413,7 +5435,7 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
TRI_V8_EXCEPTION_MEMORY(scope);
}
v8::Handle<v8::Value> result = ExecuteQueryCursorAhuacatl(vocbase, context.ptr(), parameters, doCount, batchSize);
v8::Handle<v8::Value> result = ExecuteQueryCursorAhuacatl(vocbase, context.ptr(), parameters, doCount, batchSize, ttl);
int res = context.ptr()->_error._code;
if (res == TRI_ERROR_REQUEST_CANCELED) {
@ -5446,7 +5468,7 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(errorObject));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(result);

View File

@ -64,16 +64,15 @@ TRI_general_cursor_result_t* TRI_CreateCursorResult (void* data,
TRI_general_cursor_row_t (*getAt)(TRI_general_cursor_result_t const*, const TRI_general_cursor_length_t),
TRI_general_cursor_length_t (*getLength)(TRI_general_cursor_result_t const*)) {
TRI_general_cursor_result_t* result;
if (data == NULL) {
return NULL;
if (data == nullptr) {
return nullptr;
}
result = (TRI_general_cursor_result_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_result_t), false);
TRI_general_cursor_result_t* result = static_cast<TRI_general_cursor_result_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_result_t), false));
if (result == NULL) {
return NULL;
if (result == nullptr) {
return nullptr;
}
result->_data = data;
@ -104,7 +103,7 @@ void TRI_DestroyCursorResult (TRI_general_cursor_result_t* const result) {
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeCursorResult (TRI_general_cursor_result_t* const result) {
if (result != NULL) {
if (result != nullptr) {
TRI_DestroyCursorResult(result);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, result);
}
@ -161,7 +160,7 @@ static inline TRI_general_cursor_row_t NextGeneralCursor (TRI_general_cursor_t*
cursor->_result->freeData(cursor->_result);
}
return NULL;
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@ -205,7 +204,7 @@ static TRI_json_t* GetExtraGeneralCursor (const TRI_general_cursor_t* const curs
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeGeneralCursor (TRI_general_cursor_t* cursor) {
if (cursor->_extra != NULL) {
if (cursor->_extra != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, cursor->_extra);
}
@ -225,15 +224,21 @@ TRI_general_cursor_t* TRI_CreateGeneralCursor (TRI_vocbase_t* vocbase,
TRI_general_cursor_result_t* result,
const bool doCount,
const TRI_general_cursor_length_t batchSize,
double ttl,
TRI_json_t* extra) {
TRI_general_cursor_t* cursor;
TRI_ASSERT(vocbase != nullptr);
TRI_ASSERT(vocbase != NULL);
TRI_general_cursor_t* cursor = static_cast<TRI_general_cursor_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_t), false));
cursor = (TRI_general_cursor_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_t), false);
if (cursor == nullptr) {
return nullptr;
}
if (cursor == NULL) {
return NULL;
if (ttl <= 0.0) {
ttl = 30.0; // default ttl
}
else if (ttl >= 3600.0) {
ttl = 3600.0; // max ttl
}
cursor->_vocbase = vocbase;
@ -242,9 +247,10 @@ TRI_general_cursor_t* TRI_CreateGeneralCursor (TRI_vocbase_t* vocbase,
cursor->_result = result;
cursor->_extra = extra; // might be NULL
cursor->_expires = TRI_microtime() + 3600; // default lifetime: 1h
cursor->_ttl = ttl;
cursor->_expires = TRI_microtime() + ttl;
cursor->_id = TRI_NewTickServer();
// state
cursor->_currentRow = 0;
cursor->_length = result->getLength(result);
@ -299,12 +305,13 @@ TRI_general_cursor_t* TRI_UseGeneralCursor (TRI_general_cursor_t* cursor) {
TRI_LockSpin(&store->_lock);
cursor = static_cast<TRI_general_cursor_t*>(TRI_LookupByKeyAssociativePointer(&store->_ids, &cursor->_id));
if (cursor != NULL) {
if (cursor != nullptr) {
if (cursor->_usage._isDeleted) {
cursor = NULL;
cursor = nullptr;
}
else {
++cursor->_usage._refCount;
cursor->_expires = TRI_microtime() + cursor->_ttl;
}
}
TRI_UnlockSpin(&store->_lock);
@ -321,7 +328,7 @@ void TRI_ReleaseGeneralCursor (TRI_general_cursor_t* cursor) {
TRI_LockSpin(&store->_lock);
cursor = static_cast<TRI_general_cursor_t*>(TRI_LookupByKeyAssociativePointer(&store->_ids, &cursor->_id));
if (cursor != NULL) {
if (cursor != nullptr) {
--cursor->_usage._refCount;
}
TRI_UnlockSpin(&store->_lock);
@ -338,7 +345,7 @@ bool TRI_DropGeneralCursor (TRI_general_cursor_t* cursor) {
TRI_LockSpin(&store->_lock);
cursor = static_cast<TRI_general_cursor_t*>(TRI_LookupByKeyAssociativePointer(&store->_ids, &cursor->_id));
if (cursor != NULL && ! cursor->_usage._isDeleted) {
if (cursor != nullptr && ! cursor->_usage._isDeleted) {
cursor->_usage._isDeleted = true;
result = true;
}
@ -370,9 +377,8 @@ size_t TRI_CountGeneralCursor (TRI_general_cursor_t* cursor) {
/// @brief persist the cursor by setting a timeout
////////////////////////////////////////////////////////////////////////////////
void TRI_PersistGeneralCursor (TRI_general_cursor_t* cursor,
double ttl) {
cursor->_expires = TRI_microtime() + ttl;
void TRI_PersistGeneralCursor (TRI_general_cursor_t* cursor) {
cursor->_expires = TRI_microtime() + cursor->_ttl;
}
////////////////////////////////////////////////////////////////////////////////
@ -385,8 +391,8 @@ TRI_general_cursor_t* TRI_FindGeneralCursor (TRI_vocbase_t* vocbase,
TRI_LockSpin(&store->_lock);
TRI_general_cursor_t* cursor = static_cast<TRI_general_cursor_t*>(TRI_LookupByKeyAssociativePointer(&store->_ids, &id));
if (cursor == NULL || cursor->_usage._isDeleted) {
cursor = NULL;
if (cursor == nullptr || cursor->_usage._isDeleted) {
cursor = nullptr;
}
TRI_UnlockSpin(&store->_lock);
@ -404,7 +410,7 @@ bool TRI_RemoveGeneralCursor (TRI_vocbase_t* vocbase,
TRI_LockSpin(&store->_lock);
TRI_general_cursor_t* cursor = static_cast<TRI_general_cursor_t*>(TRI_LookupByKeyAssociativePointer(&store->_ids, &id));
if (cursor == NULL || cursor->_usage._isDeleted) {
if (cursor == nullptr || cursor->_usage._isDeleted) {
result = false;
}
else {
@ -423,8 +429,8 @@ bool TRI_RemoveGeneralCursor (TRI_vocbase_t* vocbase,
TRI_general_cursor_store_t* TRI_CreateStoreGeneralCursor (void) {
TRI_general_cursor_store_t* store = static_cast<TRI_general_cursor_store_t*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_t), false));
if (store == NULL) {
return NULL;
if (store == nullptr) {
return nullptr;
}
int res = TRI_InitAssociativePointer(&store->_ids,
@ -432,12 +438,12 @@ TRI_general_cursor_store_t* TRI_CreateStoreGeneralCursor (void) {
HashKeyId,
HashElementId,
EqualKeyId,
NULL);
nullptr);
if (res != TRI_ERROR_NO_ERROR) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, store);
return NULL;
return nullptr;
}
TRI_InitSpin(&store->_lock);
@ -485,13 +491,12 @@ void TRI_CleanupGeneralCursor (TRI_general_cursor_store_t* store,
// we have deleted CURSOR_MAX_DELETE elements
while (deleteCount++ < CURSOR_MAX_DELETE || force) {
bool deleted = false;
size_t i;
for (i = 0; i < store->_ids._nrAlloc; i++) {
for (size_t i = 0; i < store->_ids._nrAlloc; i++) {
// enum all cursors
TRI_general_cursor_t* cursor = (TRI_general_cursor_t*) store->_ids._table[i];
TRI_general_cursor_t* cursor = static_cast<TRI_general_cursor_t*>(store->_ids._table[i]);
if (cursor == NULL) {
if (cursor == nullptr) {
continue;
}
@ -500,6 +505,7 @@ void TRI_CleanupGeneralCursor (TRI_general_cursor_store_t* store,
if (force ||
(cursor->_usage._refCount == 0 &&
(cursor->_usage._isDeleted || cursor->_expires < compareStamp))) {
LOG_TRACE("cleaning cursor %p, id: %llu, rc: %d, expires: %d, deleted: %d",
cursor,
(unsigned long long) cursor->_id,

View File

@ -145,6 +145,7 @@ typedef struct TRI_general_cursor_s {
uint32_t _refCount;
bool _isDeleted;
} _usage;
double _ttl;
double _expires;
struct TRI_json_s* _extra;
@ -177,6 +178,7 @@ TRI_general_cursor_t* TRI_CreateGeneralCursor (struct TRI_vocbase_s*,
TRI_general_cursor_result_t*,
const bool,
const TRI_general_cursor_length_t,
double,
struct TRI_json_s*);
////////////////////////////////////////////////////////////////////////////////
@ -225,8 +227,7 @@ size_t TRI_CountGeneralCursor (TRI_general_cursor_t*);
/// @brief persist the cursor by setting a timeout
////////////////////////////////////////////////////////////////////////////////
void TRI_PersistGeneralCursor (TRI_general_cursor_t*,
double);
void TRI_PersistGeneralCursor (TRI_general_cursor_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief lookup a cursor by its id

View File

@ -41,11 +41,6 @@ var internal = require("internal");
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoAPI
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_post_api_cursor
/// @brief create a cursor and return the first results
@ -74,6 +69,11 @@ var internal = require("internal");
/// the server to the client in one roundtrip (optional). If this attribute is
/// not set, a server-controlled default value will be used.
///
/// - *ttl*: an optional time-to-live for the cursor (in seconds). The cursor will be
/// removed on the server automatically after the specified amount of time. This
/// is useful to ensure garbage collection of cursors that are not fully fetched
/// by clients. If not set, a server-defined value will be used.
///
/// - *bindVars*: key/value list of bind parameters (optional).
///
/// - *options*: key/value list of extra options for the query (optional).
@ -349,7 +349,8 @@ function post_api_cursor(req, res) {
json.bindVars,
{
count : json.count || false,
batchSize: json.batchSize || 1000
batchSize: json.batchSize || 1000,
ttl: json.ttl
},
json.options);
}
@ -613,10 +614,6 @@ actions.defineHttp({
}
});
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"

View File

@ -345,7 +345,7 @@ function setupIndexQuery (name, func, isExampleQuery) {
result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
catch (err) {
@ -503,7 +503,7 @@ actions.defineHttp({
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}
@ -779,7 +779,7 @@ actions.defineHttp({
result = result.distance(distance);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}
@ -956,7 +956,7 @@ actions.defineHttp({
result = result.distance(distance);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}
@ -1080,7 +1080,7 @@ actions.defineHttp({
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}
@ -1235,7 +1235,7 @@ actions.defineHttp({
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}
@ -1730,7 +1730,7 @@ actions.defineHttp({
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize));
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), true, body.batchSize, body.ttl));
}
}
}