March 03, 2017
Hi all!

I make vibe-d based project and now I have problem passing messages between threads.
First some words about architecture. Each event in the system has a corresponding class that validates and performs the required actions. Each class has a nested structure with the parameters that are required for this event. Like this:

```
module vcm.bll.event.deleteSite;

import vcm.bll.basicEvent;

class DeleteSite : BasicEvent
{
	import vcm.bll.model.types : Id;
	
	struct Params
	{
		Id siteId;
	}

	mixin EventConstructor;
	
	override bool canDo()
	{
		import std.conv : to;
		
		return errorList
			.addIf(!engine.sites.contains(params.siteId), "SiteModel with id "~params.siteId.to!string~" is not found")
			.isEmpty();
	}
	
	override EventResult doIt()
	{
		engine.db.execute("DELETE FROM sites WHERE id=?", params.siteId);

		return EventResult(true,[],0);
	}

}
```
I have Engine class object which resides in own thread and listen message queue for messages with event parameters. After receiving message corresponding handler is executed, and message with EventResult object sent back to caller thread (Task). For every event type there is HTTP request handler, who make EventType.Params structure, send it to engine Task, then do receiveOnly!EventResult and take actions according to it. The only proble with this approach was a lot of boilerplate in engine receive() call because of big amout of event types. I resolve it by this way (is this possible without string mixin?):

```
private static string getReceiver(EventTypes...)() pure
	{
		import std.traits;
		
		string eventHandlers;
		foreach(EventType; EventTypes)
			eventHandlers ~= `,(`~EventType.stringof~`.Params params, Task caller, Id userId){
					auto event = scoped!`~EventType.stringof~`(userId, params);
					event.setEngine(this);
					caller.send(event.execute());
				}`;

		return
			`receive
				((ExitMessage _){ exitFlag = true; }
				,(LogMessage entry){ logger.log(entry.message); }
			    `
				~eventHandlers
				~");";
	}
	
	private void run()
	{
		import vibe.core.concurrency : receive, send;
		import std.typecons: scoped;
		import vcm.bll.event;
		
		bool exitFlag = false;
		
		while(!exitFlag)
			mixin(getReceiver!AllEvents);
	}

```

After adding another event I ran into a problem:

```
Task terminated with unhandled exception: Range violation
core.exception.RangeError@source/vcm/bll/idContainer.d(44): Range violation
----------------
...
vcm.bll.event.deleteSite.DeleteSite.canDo() [0xd8dd5a]
source/vcm/bll/basicEvent.d:182 bool vcm.bll.basicEvent.BasicEvent.check() [0xd2f8bc]
source/vcm/bll/basicEvent.d:197 vcm.bll.basicEvent.EventResult vcm.bll.basicEvent.BasicEvent.execute() [0xd2f9a5]
source/vcm/bll/engine.d-mixin-173:198 _D3vcm3bll6engine6Engine3runMFZ9__lambda8MFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vibe4core4task4TaskmZv [0xd34375]
/usr/include/dmd/phobos/std/concurrency.d:168 void std.concurrency.Message.map!(void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong)).map(void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong)) [0xc7df3d]
/usr/include/dmd/phobos/std/concurrency.d:1956 _D3std11concurrency10MessageBox1467__T3getTDFNaNbNiNfS3vcm3bll7commons11ExitMessageZvTDFS3vcm3bll6engine10LogMessageZvTDFS3vcm3bll5event9addDevice9AddDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9addClient9AddClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addRole7AddRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addUser7AddUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addSite7AddSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event13adminEditUser13AdminEditUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event14changePassword14ChangePassword6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteDevice12DeleteDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteRole10DeleteRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteUser10DeleteUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10editDevice10EditDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event5login5Login6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event8register8Register6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event11adminLogout11AdminLogout6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event15adminEditClient15AdminEditClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9importMdb9ImportMdb6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteClient12DeleteClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event18managerIncludeUser18ManagerIncludeUser6ParamsS4vibe4core
/usr/include/dmd/phobos/std/concurrency.d:2037 _D3std11concurrency10MessageBox1467__T3getTDFNaNbNiNfS3vcm3bll7commons11ExitMessageZvTDFS3vcm3bll6engine10LogMessageZvTDFS3vcm3bll5event9addDevice9AddDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9addClient9AddClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addRole7AddRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addUser7AddUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addSite7AddSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event13adminEditUser13AdminEditUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event14changePassword14ChangePassword6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteDevice12DeleteDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteRole10DeleteRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteUser10DeleteUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10editDevice10EditDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event5login5Login6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event8register8Register6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event11adminLogout11AdminLogout6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event15adminEditClient15AdminEditClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9importMdb9ImportMdb6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteClient12DeleteClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event18managerIncludeUser18ManagerIncludeUser6ParamsS4vibe4core
/usr/include/dmd/phobos/std/concurrency.d:2115 bool std.concurrency.MessageBox.get!(pure nothrow @nogc @safe void delegate(vcm.bll.commons.ExitMessage), void delegate(vcm.bll.engine.LogMessage), void delegate(vcm.bll.event.addDevice.AddDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addClient.AddClient.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addRole.AddRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addUser.AddUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addSite.AddSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditUser.AdminEditUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.changePassword.ChangePassword.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteDevice.DeleteDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteRole.DeleteRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteUser.DeleteUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.editDevice.EditDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.login.Login.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.register.Register.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminLogout.AdminLogout.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditClient.AdminEd
/usr/include/dmd/phobos/std/concurrency.d:700 void std.concurrency.receive!(pure nothrow @nogc @safe void delegate(vcm.bll.commons.ExitMessage), void delegate(vcm.bll.engine.LogMessage), void delegate(vcm.bll.event.addDevice.AddDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addClient.AddClient.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addRole.AddRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addUser.AddUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addSite.AddSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditUser.AdminEditUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.changePassword.ChangePassword.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteDevice.DeleteDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteRole.DeleteRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteUser.DeleteUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.editDevice.EditDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.login.Login.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.register.Register.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminLogout.AdminLogout.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditClient.AdminEditClient
source/vcm/bll/engine.d:172 void vcm.bll.engine.Engine.run() [0xd33c66]
../../.dub/packages/vibe-d-0.7.30/vibe-d/source/vibe/core/core.d:592 void vibe.core.core.makeTaskFuncInfo!(void delegate()).makeTaskFuncInfo(ref void delegate()).callDelegate(vibe.core.core.TaskFuncInfo*) [0xc2b8fc]
../../.dub/packages/vibe-d-0.7.30/vibe-d/source/vibe/core/core.d:1221 void vibe.core.core.CoreTask.run() [0xf2ecc6]
??:? void core.thread.Fiber.run() [0x103f65f]
??:? fiber_entryPoint [0x103f3c2]
??:? [0xffffffff]
core.exception.InvalidMemoryOperationError@src/core/exception.d(693): Invalid memory operation
----------------

```
The problem here - not the exception itself, but the fact that the stack consists a call to void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, ...) because I am quite sure that the parameter passed is ManagerIncludeUser.Params. I see very long symbols in the stack trace. Is this possible I hit some restriction on the length of the symbol or the number of delegates in receive() and it leads to broken mapping?