On Thu, 24 Oct 2013 06:46:05 GMT, Sönke Ludwig wrote:

On Wed, 23 Oct 2013 08:32:18 GMT, Stephan Dilly wrote:

Hi guys,
I am just investigating how to implement long polling with vibe.

Since I just started using vibe.d I am totally new to the concepts of fibers and the vibe.d API.

But from what I found I thought using a ManualEvent to wait in a http handleRequest until a timeout happens or another fiber triggers an emit on the ManualEvent and then returning the response should do the trick.
The problem is, that when the timeout happens or the emit is triggerd from another fiber (another GET request that is) then the response is not valid anymore.

Any ideas ? Is my whole concept wrong ?

Regards

I'm not 100% sure what the issue is, but I'd use a TaskCondition instead of a raw ManualEvent to avoid the possibility for accidental race conditions. Just to be on the same page, this is about what I would do:

// possibly __gshared
TaskMutex s_mutex;
TaskCondition s_condition;
bool[Task] s_tasks;

// possibly shared static this
static this()
{
    s_mutex = new TaskMutex;
    s_condition = new TaskCondition;
}

void handleLongPoll(HTTPServerRequest req, HTTPServerResponse res)
{
    auto task = Task.getThis();
    s_tasks[task] = false;
    auto timeout = Clock.currTime(UTC()) + 10.seconds;
    bool timed_out = false;
    synchronized (s_mutex) {
        while (!s_tasks[task]) {
            auto tm = Clock.currTime(UTC());
            timed_out = tm >= timeout;
            if (timed_out) break;
            s_condition.wait(timeout - tm);
        }
        s_tasks.remove(task);
    }
    if (timed_out) {
        // write timeout response
    } else {
        // write normal response
    }
}

void onHandleEvent()
{
    synchronized (s_mutex) {
        foreach (t, ref triggered; s_tasks)
            triggered = true;
    }
    s_condition.notifyAll();
}

Or do you mean that the response is not valid anymore because a connection timeout occurred somewhere? I think such a timeout should only occur in the client, in which case it should be OK. The client would simple have to start another poll request and the server request handler would simply throw an exception and terminate.

Thanks for you reply, I don't get the stuff you are doing with this aa of Tasks. Why is that necessary ?
What is working for me now is the following solution, but it turns up more questsions :D

class SockJsConnection
{
	TaskMutex mutex;
	TaskCondition condition;
	bool dataPending;
	
	this()
	{
		mutex = new TaskMutex;
		condition = new TaskCondition(mutex);
	}
	
	void handleLongPoll(HTTPServerRequest req, HTTPServerResponse res)
	{
		synchronized (mutex) {
			condition.wait(10.seconds);
		}
		
		if (dataPending) {
			// write timeout response
		} else {
			// write normal response
		}
	}
	
	void write()
	{
		dataPending = true;
		condition.notifyAll();
	}
}

Why do I need to synchronize over the mutex to wait ? I thought vibe.d is using fibers and async io for concurrency ? Can I configure how it scales over multiple threads ?
What's the difference between condition.notify() and condition.notifyAll() - for me the code seems to be exactly the same ;)

Last but not least: Is there a irc channel for D ?
We are seeing a realistic chance to use vibe.d in our company for a server backend, but we would like to be able to shorten the communication routes as much as possible ;)