Vibe.d HTTP Request strange behavior - Second attempt to send HTTP request failed
We would like to use vibe.d for a simple backend, but run into strange behavior with HTTP request. The backend is simple: it receives requests from clients and makes requests for some json contents. Now, the code is only a vibe.d basic http server and a sample http request from vibe.d example. Sometimes(very often) we got the error: "statusMessage":"Second attempt to send HTTP request failed.","statusDebugMessage":"object.Exception@../../../.dub/packages/vibe-d-0.8.6/vibe-d/http/vibe/http/client.d(615): Second attempt to send HTTP request failed.\n\n/usr/include/dlang/dmd/std/exception.d:516 pure..." It starts happening when there is no request for a few seconds. The error comes only, when I read the response (res.readJson(); or res.bodyReader.readAllUTF8();). Our simple test case is: start vibe.d server, open a browser. Opening our server url makes a http request to our vibe.d server, which tries to make a http request to an another server. I found some related content here: https://github.com/vibe-d/vibe.d/issues/2290 And here (second commenter is me): https://github.com/vibe-d/vibe.d/issues/2451 We use the latest stable vibe.d(0.8.6), dub and dmd. We tried several things, but nothing works.
Calling C functions
I have a two questions about calling C functions from D. (1) When passing a D callback to a C function, is there a way to write the code without having to prefix the callback declaration with "extern(C)"? It's not a big deal adding the prefix to the D function declaration. It just seems odd to me to prefix D code with "extern(C)". For example, the following code works: extern(C) void cfunc(void function(int)); extern(C) void dcallback(int x) {...} <-- Why extern(C)? cfunc(); Can this be rewritten, dropping the prefix from the second line? If not, it would be helpful to know why "extern(C)" is needed here too. (2) Is there a way to restrict the invocation of a linked C function to one specific D function? If the C header is defined in one of the core.stdc libraries, the import statement can either be global or inside a specific D function -- both work. In contrast, when the C function prototype is written directly into the D program (as above), the linker complains unless this declaration is made global. If it's possible to restrict the scope of the C function to just one D function, I'll take advantage. (I'm using dmd, if that makes a difference.) Thanks
Re: Iterators in structs
On Thursday, 25 June 2020 at 18:47:42 UTC, repr-man wrote: struct ChunksOf(R) { Chunks!R iter; this(R r, size_t width) { this.iter = r.chunks(width); assert(is(typeof(iter) == Chunks!R)); } } This works, only if I change the declaration of x in main() to: auto x = ChunksOf!(chain(a[], b[]))(chain(a[], b[]), 2); This requires me to pass the iterator as a template parameter and a regular parameter. Since this is a bit redundant, and I wanted to know if there was a better way to do it. Thanks for the help! The usual solution is to create a helper function: ChunksOf!R chunksOf(R)(R r, size_t width) { return ChunksOf!R(r, width); } The compiler can infer template arguments for function calls, so you can call it like this: auto x = chunksOf(chain(a[], b[]), 2);
Iterators in structs
As an extension of my previous thread (https://forum.dlang.org/thread/nupwljahyutnyxdvp...@forum.dlang.org), I wanted to ask about iterators in structs. I will start with the following code: void main() { int[5] a = [0, 1, 2, 3, 4]; int[5] b = [5, 6, 7, 8, 9]; auto x = ChunksOf(chain(a[], b[]), 2); } struct ChunksOf { this(R)(R r, size_t width) { auto iter = r.chunks(width); assert(is(typeof(iter) == Chunks!R)); } } This code works as expected. However, if the struct changes to: struct ChunksOf { Chunks!R iter; this(R)(R r, size_t width) { this.iter = r.chunks(width); assert(is(typeof(iter) == Chunks!R)); } } it doesn't compile because R is only in the scope of the constructor. This leads me to change the struct to: struct ChunksOf(R) { Chunks!R iter; this(R r, size_t width) { this.iter = r.chunks(width); assert(is(typeof(iter) == Chunks!R)); } } This works, only if I change the declaration of x in main() to: auto x = ChunksOf!(chain(a[], b[]))(chain(a[], b[]), 2); This requires me to pass the iterator as a template parameter and a regular parameter. Since this is a bit redundant, and I wanted to know if there was a better way to do it. Thanks for the help!
Re: Passing iterators into functions
On Thursday, 25 June 2020 at 03:35:00 UTC, repr-man wrote: This seems to have to do with the fact that all iterators return their own unique type. Could someone help me understand the reason behind this design and how to remedy my situation? Ranges conform to well-defined interfaces. Given that the algorithms in Phobos are templates and use structs rather than classes, this means the interfaces are checked at compile time (see the `is*` templates in std.range.primitives [1]). It also means that there is no concrete range "type" returned by these functions. That's why all of them return `auto` instead of a specific type. You never need to know the specific type of a range. Arrays are ranges only because of the free-function implementation of the range interfaces in std.range.primitives which all take an array as the first argument so that they may be called using UFCS in any templated range algorithm. So when you input an array to a range algorithm, the algorithm has no idea it has an array. It just calls R.emtpy, R.front, etc., without ever caring what the actual type is. And you can chain them because each algorithm wraps the input range with custom range type that actually implements the algorithm (in e.g., `popFront`--that's also why ranges are lazy), and that's what is returned. In a chain of function calls, popFront is called on the outermost range, which calls popFront on its wrapped range, which calls popFront on its wrapped range, etc. So if you append std.array.array to the end of the chain, it will kick off execution of the whole chain of calls by making the first call to popFront in order to copy the result into a new array. Chapter 6, "Understanding Ranges", from "Learning D" is available freely online [2]. You should give it a read. [1] https://dlang.org/phobos/std_range_primitives.html [2] https://hub.packtpub.com/understanding-ranges/
Re: Passing iterators into functions
Collection elements are accessed by ranges in D. Although both iterators and ranges fundamentally do the same thing (access elements). More accurately, ranges correspond to a pair iterators. On 6/24/20 8:35 PM, repr-man wrote: > auto func(R)(R r, size_t width) > if(isRandomAccessRange!R) > { > return r.chunks(width); > } > > void main() > { > int[5] a = [0, 1, 2, 3, 4]; > int[5] b = [5, 6, 7, 8, 9]; > auto x = func!(int[])(chain(a[], b[]), 5); Is there a reason why you specify the template argument there? > This seems to have to do with the fact that all iterators return their > own unique type. When the element is normally different, there would be no way of using one type anyway. This is similar to how vector::iterator is a different type from e.g. vector::iterator. > Could someone help me understand the reason behind > this design Andrei Alexandrescu has the following article on D's ranges: https://www.informit.com/articles/printerfriendly/1407357 > and how to remedy my situation? Just don't specify the function template argument and it will work. Ali