public void SelectTransactionKey(string session, Action<string> y) { try { var data = new SystemConsoleOut(); Action<long> yield = id => { y("" + id); }; data.SelectTransactionKey( e: new SystemConsoleOutQueries.SelectTransaction { session = int.Parse(session) }, yield: yield ); //y("CheckDatabase ok"); } catch (Exception ex) { //__ConsoleToDatabaseWriter.InternalWriteLine("SelectTransactionKey error " + new { ex }); //y("CheckDatabase error " + new { ex }); } //var c = new __ConsoleToDatabaseWriter(int.Parse(session)); //c.data.SelectTransactionKey( // new SystemConsoleOutQueries.SelectTransaction { session = int.Parse(session) }, // id => // { // y("" + id); // } //); }
public /* will not be part of web service itself */ void Handler(WebServiceHandler h) { // I/System.Console(12961): Caused by: java.lang.NullPointerException //I/System.Console(12961): at ConsoleByCookie.ApplicationWebService.Handler(ApplicationWebService.java:162) //I/System.Console(12961): ... 17 more var Accepts = h.Context.Request.Headers["Accept"]; __ConsoleToDatabaseWriter.InternalWriteLine( new { h.Context.Request.Path, Accepts } + Environment.NewLine ); //EventSource's response has a MIME type ("text/plain") that is not "text/event-stream". Aborting the connection. if (h.Context.Request.Path == "/wait") { Thread.Sleep(5000); h.CompleteRequest(); return; } if (Accepts != null) if (Accepts.Contains("text/event-stream")) { //try //{ // http://www.w3schools.com/html/html5_serversentevents.asp // http://caniuse.com/eventsource // http://www.w3.org/TR/eventsource/ // https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events // http://opensource.apple.com/source/WebCore/WebCore-1640.1/page/EventSource.cpp?txt // http://stackoverflow.com/questions/13166284/eventsources-response-has-a-mime-type-text-html-that-is-not-text-event-str h.Context.Response.ContentType = "text/event-stream"; h.Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); //EventSource's response has a MIME type ("text/plain") that is not "text/event-stream". Aborting the connection. // A potentially dangerous Request.QueryString value was detected from the client (e="<client value="15.12..."). //var _e_xml = h.Context.Request.RawUrl // .SkipUntilLastOrEmpty("?") // .SkipUntilOrEmpty("e=") // .TakeUntilIfAny("&"); //var _e_xml_decoded = HttpUtility.UrlDecode(_e_xml); // No Cookies on andrid yet? // http://en.wikipedia.org/wiki/List_of_HTTP_header_fields var header_cookie = h.Context.Request.Headers["Cookie"]; //Implementation not found for type import : //System.Web.HttpRequest :: System.Web.HttpCookieCollection get_Cookies() //Did you forget to add the [Script] attribute? //Please double check the signature! //type: ConsoleByCookie.ApplicationWebService offset: 0x014c method:Void Handler(ScriptCoreLib.Ultra.WebService.WebServiceHandler) //foreach (var item in collection) //{ //} var cookie_session = h.Context.Request.Cookies["session"]; //no session cookie? { header_cookie = session=2006041647; xfoo=foo; random=2376781287 } #region workaround if (cookie_session == null) cookie_session = new HttpCookie( "session", header_cookie.SkipUntilLastOrEmpty("session=").TakeUntilOrEmpty(";") ); #endregion if (cookie_session == null) { //__ConsoleToDatabaseWriter.InternalWriteLine("no session cookie? " + new { header_cookie }); h.Context.Response.StatusCode = 500; h.CompleteRequest(); return; } //var _e = XElement.Parse(cookie_session.Value); var session = int.Parse(cookie_session.Value); //var c = new __ConsoleToDatabaseWriter(session); var data = new SystemConsoleOut(); var header_id = h.Context.Request.Headers["Last-Event-ID"]; var id = 0; if (header_id != null) { //__ConsoleToDatabaseWriter.InternalWrite("Continue " + new { session, header_id }.ToString() + Environment.NewLine); //id = int.Parse(XElement.Parse(header_id).Attribute("id").Value); id = int.Parse(header_id); } else { data.SelectTransactionKey(session, nextid => { id = (int)nextid; //var xml = new XElement("e", // new XAttribute("id", id) //); //__ConsoleToDatabaseWriter.InternalWrite("Reset To " + new { session, id }.ToString() + Environment.NewLine); h.Context.Response.Write("id: " + id + "\n\n"); //h.Context.Response.Write("event: SystemConsoleOut\n"); h.Context.Response.Write("data: reset to " + new { id } + " \n\n"); h.Context.Response.Flush(); } ); } int retry = 1000 / 30; Action CheckForUpdates = delegate { Action later = delegate { }; data.SelectTransactionKey(session, nextid => { if (id == (int)nextid) { later = delegate { // no updates yet // it is imortant to sleep // only if we released the database. // otherwise other threads will wait for us! Thread.Sleep(retry); }; return; } data.SelectContentUpdates( new SystemConsoleOutQueries.SelectContentUpdates { id = id, nextid = (int)nextid, session = session }, r => { string value = r.value; h.Context.Response.Write("event: SystemConsoleOut\n"); h.Context.Response.Write("data: " + value.Replace("\r", "\\r").Replace("\n", "\\n") + "\n\n"); // wont work on appengine? // https://groups.google.com/forum/?fromgroups=#!topic/google-appengine-java/LWWRMP5KU1w // https://developers.google.com/appengine/docs/java/runtime#Responses // limited to 32MB // need to use channel API instead? // https://developers.google.com/appengine/docs/python/channel/overview h.Context.Response.Flush(); } ); id = (int)nextid; //var xml = new XElement("e", // new XAttribute("id", id) //); //h.Context.Response.Write("id: " + xml.ToString() + "\n\n"); h.Context.Response.Write("id: " + id + "\n\n"); h.Context.Response.Flush(); } ); later(); }; // loop forever? var t = new Stopwatch(); t.Start(); //for (int i = 0; i < 1024; i++) while (t.ElapsedMilliseconds < 7000) { // http://stackoverflow.com/questions/9743253/how-to-detect-a-disconnection-when-using-server-sent-events-on-asp-net //if (!h.Context.Response.IsClientConnected) //{ // __ConsoleToDatabaseWriter.InternalWrite("!IsClientConnected"); // break; //} //__ConsoleToDatabaseWriter.InternalWrite("CheckForUpdates " + new { Thread.CurrentThread.ManagedThreadId, session, i, id }.ToString() + Environment.NewLine); CheckForUpdates(); } //Thread.Sleep(5000); #region prevent error 2, required if we did not send any other events h.Context.Response.Write("retry: " + retry + "\n\n"); h.Context.Response.Write("data: retry later\n\n"); h.Context.Response.Flush(); #endregion h.CompleteRequest(); //} //catch //(Exception ex) //{ // throw; //} } __ConsoleToDatabaseWriter.InternalWrite( new { h.Context.Request.Path, Accepts, h.Context.Response.ContentType } + " done!" + Environment.NewLine ); }