void ExtendBuffer(Response response) { if (this.IsOpen) { if (response.IsPartial) { //SUCCESS_PARTIAL foreach (var jToken in response.Data) { items.Enqueue(jToken); } } else if (response.IsSequence) { //SUCCESS_SEQUENCE foreach (var jToken in response.Data) { items.Enqueue(jToken); } this.SequenceFinished(); } else if (response.IsError) { var ex = response.MakeError(query); this.Shutdown(ex); throw ex; } else { throw new NotSupportedException( $"Cursor cannot extend the response. The response was not a SUCCESS_PARTIAL or SUCCESS_SEQUENCE. The response type the cursor received was {response.Type}."); } } }
/// <summary> /// Asynchronously ensures that previous queries executed with NoReplyWait have /// been processed by the server. Note that this guarantee only apples to queries /// run on the same connection. /// </summary> protected virtual async Task RunQueryWaitAsync(Query query, CancellationToken cancelToken) { Response res = await SendQuery(query, cancelToken, awaitResponse: true).ConfigureAwait(false); if (res.IsWaitComplete) { return; } if (res.IsError) { throw res.MakeError(query); } throw new ReqlDriverError( $"The query response is not WAIT_COMPLETE. The returned query is {res.Type}. You need to call the appropriate run method that handles the response type for your query."); }
/// <summary> /// Fast SUCCESS_SEQUENCE or SUCCESS_PARTIAL conversion without DLR dynamic. /// </summary> protected virtual async Task<Cursor<T>> RunQueryCursorAsync<T>(Query query, CancellationToken cancelToken) { Response res = await SendQuery(query, cancelToken, awaitResponse: true).ConfigureAwait(false); if (res.IsPartial || res.IsSequence) { return new Cursor<T>(this, query, res); } if (res.IsError) { throw res.MakeError(query); } throw new ReqlDriverError( $"The query response cannot be converted to a Cursor<T>. The run helper " + $"works with SUCCESS_SEQUENCE or SUCCESS_PARTIAL results. The server " + $"response was {res.Type}. If the server response can be handled by " + $"this run method check T. Otherwise, if the server response cannot " + $"be handled by this run helper use `.RunAtom<T>` or `.RunResult<T>`."); }
/// <summary> /// Run the query but it's return type is standard dynamic. /// </summary> protected async Task<dynamic> RunQueryAsync<T>(Query query, CancellationToken cancelToken) { //If you need to continue after an await, **while inside the driver**, //as a library writer, you must use ConfigureAwait(false) on *your* //await to tell the compiler NOT to resume //on synchronization context (if one is present). // //The top most await (your user) will capture the correct synchronization context //(if any) when they await on a query's run. // // https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Async-library-methods-should-consider-using-Task-ConfigureAwait-false- // http://blogs.msdn.com/b/lucian/archive/2013/11/23/talk-mvp-summit-async-best-practices.aspx // Response res = await SendQuery(query, cancelToken, awaitResponse: true).ConfigureAwait(false); if (res.IsAtom) { try { if (typeof(T).IsJToken()) { if (res.Data[0].Type == JTokenType.Null) return null; FormatOptions fmt = FormatOptions.FromOptArgs(query.GlobalOptions); Converter.ConvertPseudoTypes(res.Data[0], fmt); return res.Data[0]; } return res.Data[0].ToObject(typeof(T), Converter.Serializer); } catch (IndexOutOfRangeException ex) { throw new ReqlDriverError("Atom response was empty!", ex); } } else if (res.IsPartial || res.IsSequence) { return new Cursor<T>(this, query, res); } else if (res.IsWaitComplete) { return null; } else { throw res.MakeError(query); } }
/// <summary> /// Fast SUCCESS_ATOM or SUCCESS_SEQUENCE conversion without the DLR dynamic /// </summary> private async Task<T> RunQueryResultAsync<T>(Query query, CancellationToken cancelToken) { Response res = await SendQuery(query, cancelToken, awaitResponse: true).ConfigureAwait(false); if (res.IsAtom) { try { if (typeof(T).IsJToken()) { if (res.Data[0].Type == JTokenType.Null) return (T)(object)null; FormatOptions fmt = FormatOptions.FromOptArgs(query.GlobalOptions); Converter.ConvertPseudoTypes(res.Data[0], fmt); return (T)(object)res.Data[0]; //ugh ugly. find a better way to do this. } return res.Data[0].ToObject<T>(Converter.Serializer); } catch (IndexOutOfRangeException ex) { throw new ReqlDriverError("Atom response was empty!", ex); } } if (res.IsSequence) { if (typeof(T).IsJToken()) { FormatOptions fmt = FormatOptions.FromOptArgs(query.GlobalOptions); Converter.ConvertPseudoTypes(res.Data, fmt); return (T)(object)res.Data; //ugh ugly. find a better way to do this. } return res.Data.ToObject<T>(Converter.Serializer); } if (res.IsError) { throw res.MakeError(query); } throw new ReqlDriverError( $"The query response cannot be converted to an object of T or List<T> " + $"because the server response was {res.Type}. The `.RunResult<T>` helper " + $"only works with SUCCESS_ATOM or SUCCESS_SEQUENCE responses. When the query " + $"response grows larger (over 100K), the response type from the server " + $"can change from SUCCESS_SEQUENCE to SUCCESS_PARTIAL; in which case, you'll " + $"need to use `.RunCursor` that handles both SUCCESS_SEQUENCE and SUCCESS_PARTIAL " + $"response types. The `.RunResult` run helper is only meant to be a " + $"convenience method for relatively quick and smaller responses."); }
/// <summary> /// Fast SUCCESS_ATOM conversion without the DLR dynamic /// </summary> protected virtual async Task<T> RunQueryAtomAsync<T>(Query query, CancellationToken cancelToken) { Response res = await SendQuery(query, cancelToken, awaitResponse: true).ConfigureAwait(false); if (res.IsAtom) { try { if (typeof(T).IsJToken()) { if (res.Data[0].Type == JTokenType.Null) return (T)(object)null; FormatOptions fmt = FormatOptions.FromOptArgs(query.GlobalOptions); Converter.ConvertPseudoTypes(res.Data[0], fmt); return (T)(object)res.Data[0]; //ugh ugly. find a better way to do this. //return res.Data[0].ToObject<T>(); } return res.Data[0].ToObject<T>(Converter.Serializer); } catch (IndexOutOfRangeException ex) { throw new ReqlDriverError("Atom response was empty!", ex); } } if (res.IsError) { throw res.MakeError(query); } throw new ReqlDriverError( $"The query response cannot be converted to an object of T or List<T>. This run helper works with SUCCESS_ATOM results. The server response was {res.Type}. If the server response can be handled by this run method try converting to T or List<T>. Otherwise, if the server response cannot be handled by this run helper use another run helper like `.RunCursor` or `.RunResult<T>`."); }