I have some data that I would like to store for each user (session). I tried injecting it into curdoc().session_context but it appears to not be a simple data structure like a dict, it's a SessionContext object, and moreover, from reading the docs, I can't tell how to manipulate it (or it appears it is not meant to be): https://docs.bokeh.org/en/latest/docs/reference/document.html
How can I store some arbitrary local data for each user that gets destroyed when the session is destroyed?
I think you are overthinking this, then. If you want to store data between callbacks that is contained in one session, you don't need to do anything special. You could (for example) define a module level variable data = {} in the Bokeh app then callbacks can read and write to the dict however you need:
data = {}
def button_callback(attr, old, new):
# write some to session "data store"
data['foo'] = 'bar'
def button_callback():
# read some data from session "data store"
print(data['foo'])
Every session will get its own instance of data inaccessible to any other session, that will disappear whenever the session ends.
Obviously this is fairly simplistic. A more sophisticated version might define a class with a well-defined API for storing/retrieving data, and make a module level instance of the class for callbacks to use, instead of a bare dict.
With bokeh serve using Bokeh 2.1.1, I find that Python instance variables are unique to each session, so they can store session-specific data. For example, run this Bokeh app in three browser windows and click the Test button in window 1 then 2 then 3 and again in window 1 then 2 then 3 - the console messages show that each session has its own unique mySession value:
class InstanceVar():
def __init__(self, title):
self.testButton = Button(label="Test", button_type="primary")
self.testButton.on_click(self._test)
self.mySession = id(curdoc().session_context)
print("Set mySession={}".format(self.mySession))
def _test(self):
print("mySession={}".format(self.mySession))
But Python class variables seem to be shared by all sessions; when I run the following app in the same way, all three sessions print the mySession value of the most recently started session since they are all using the same class variable in memory:
class ClassVar():
mySession = None
def __init__(self, title):
self.testButton = Button(label="Test", button_type="primary")
self.testButton.on_click(self._test)
ClassVar.mySession = id(curdoc().session_context)
print("Set mySession={}".format(ClassVar.mySession))
def _test(self):
print("mySession={}".format(ClassVar.mySession))
So I assume from this that Bokeh Server only imports each class once and therefore all sessions/users share the class variables.
Related
We appear to have a problem with MDriven generating the same ECO_ID for multiple objects. For the most part it seems to happen in conjunction with unexpected process shutdowns and/or server shutdowns, but it does also happen during normal activity.
Our system consists of one ASP.NET application and one WinForms application. The ASP.NET app is setup in IIS to use a single worker process. We have a mixture of WebForms and MVC, including ApiControllers. We're using a rather old version of the ECO packages: 7.0.0.10021. We're on VS 2017, target framework is 4.7.1.
We have it configured to use 64 bit integers for object id:s. Database is Firebird. SQL configuration is set to use ReadCommitted transaction isolation.
As far as I can tell we have configured EcoSpaceStrategyHandler with EcoSpaceStrategyHandler.SessionStateMode.Never, which should mean that EcoSpaces are not reused at all, right? (Why would I even use EcoSpaceStrategyHandler in this case, instead of just creating EcoSpace normally with the new keyword?)
We have created MasterController : Controller and MasterApiController : ApiController classes that we use for all our controllers. These have a EcoSpace property that simply does this:
if (ecoSpace == null)
{
if (ecoSpaceStrategyHandler == null)
ecoSpaceStrategyHandler = new EcoSpaceStrategyHandler(
EcoSpaceStrategyHandler.SessionStateMode.Never,
typeof(DiamondsEcoSpace),
null,
false
);
ecoSpace = (DiamondsEcoSpace)ecoSpaceStrategyHandler.GetEcoSpace();
}
return ecoSpace;
I.e. if no strategy handler has been created, create one specifying no pooling and no session state persisting of eco spaces. Then, if no ecospace has been fetched, fetch one from the strategy handler. Return the ecospace. Is this an acceptable approach? Why would it be better than simply doing this:
if (ecoSpace = null)
ecoSpace = new DiamondsEcoSpace();
return ecoSpace;
In aspx we have a master page that has an EcoSpaceManager. It has been configured to use a pool but SessionStateMode is Never. It has EnableViewState set to true. Is this acceptable? Does it mean that EcoSpaces will be pooled but inactivated between round trips?
It is possible that we receive multiple incoming API calls in tight succession, so that one API call hasn't been completed before the next one comes in. I assume that this means that multiple instances of MasterApiController can execute simultaneously but in separate threads. There may of course also be MasterController instances executing MVC requests and also the WinForms app may be running some batch job or other.
But as far as I understand id reservation is made at the beginning of any UpdateDatabase call, in this way:
update "ECO_ID" set "BOLD_ID" = "BOLD_ID" + :N;
select "BOLD_ID" from "ECO_ID";
If the returned value is K, this will reserve N new id:s ranging from K - N to K - 1. Using ReadCommitted transactions everywhere should ensure that the update locks the id data row, forcing any concurrent save operations to wait, then fetches the update result without interference from other transactions, then commits. At that point any other pending save operation can proceed with its own id reservation. I fail to see how this could result in the same ID being used for multiple objects.
I should note that it does seem like it sometimes produces id duplicates within one single UpdateDatabase, i.e. when saving a set of new related objects, some of them end up with the same id. I haven't really confirmed this though.
Any ideas what might be going on here? What should I look for?
The issue is most likely that you use ReadCommitted isolation.
This allows for 2 systems to simultaneously start a transaction, read the current value, increase the batch, and then save after each other.
You must use Serializable isolation for key generation; ie only read things not currently in a write operation.
MDriven use 2 settings for isolation level UpdateIsolationLevel and FetchIsolationLevel.
Set your UpdateIsolationLevel to Serializable
I have a PlayerPref that spawn more objects in OnStartLocalPlayer().
So in OnStartLocalPlayer() it call Command(assume that called on server) that instantiate GameObject and setup some values of its scripts. At the end it calls SpanWithClientAuthority()...
The thing is that on owner client and on server those script tweeks are correct, but on all other clients it lost all that settings(ex. gameobject ref etc). What do I do wrong?
Once more in nutshell: playerPref GO must have ref list of several other objects, and those objects must have ref to that playerPref GO. (making them part of playerPref GO is not a solution).
If I understand your problem correctly, you need the references to be set across all clients who have the same game object. [Command]'s are for client to server. What you need is a [ClientRpc]. Make the OnStartLocalPlayer() call a [ClientRpc] function, in that function (ex: RpcSetRefs()) set the references you need each client to have.
I have a QWidget ( lets call it parentWidget ) on which I have enabled the input method by setting the attribute : Qt::WA_InputMethodEnabled.
My interest is to pop up a Line dialog ( lets call it inputMethodEditor ) which should further handle all the input of the text.
Now I have read that the inputMethod works like a session, means it has states like startedToCompose, composing, completing. While the input method is in startedToCompose or composing state it sends the string under composition in preEditString through inputMethodEvent and once the session completes it sends the final composed string in commitString().
My intent is to finish this session started on parentWidget as soon as the inputMethodEditor dialog is popped up.
So, the question is, whether there is a way to close this session programmatically.?
After exploring a while, I could figure it out, I don't know how I overlooked it earlier.
So the trick is to invoke QInputMethod::reset function.
Something like this:
QApplication* application = static_cast<QApplication *>(QApplication::instance());
application->inputMethod()->reset();
This is mostly a Functional Programming question rather than an Elixir one, but since I'm learning Elixir it would be nice if someone can answer it using that language. Even so, if someone wants to give a more general answer it'll be appreciated.
I'm an OO programmer myself and I can't wrap my head around how to change the behavior of a component based on a configuration file (for example).
Example:
I have an application that loads/saves users from a database. In a production environment, I want my users to be saved and retrieved from a MongoDB database, while in development and testing I want to use an in-memory map. If I was programming given system in an OO language (Lets say Java), I would simply make an Interface named "UserRepository" with 2 implementations: "MemoryUserRepository" and "MongoDBUserRepository". I would then instantiate the corresponding Repository based on a configuration file (or hardcoding it, it doesn't matter) at startup and right after it, all the objects that interact with the Repository will never know its implementation (they will use a repository, but will never care if it's in memory or in mongo).
That gives me the ability to create as many implementations as I want and the only thing I need to do to change the behavior of the system is instantiate the implementation that I want to use.
I want the same behavior but in Elixir (let's use the same example). Since it's not an Object Oriented language I can't use the above approach. Obviously I want it to be extensible (I could easily pass a String with the type of repository I want to use in each call and use pattern matching to determine what behavior to use, but that doesn't scale well because every time I'll want to add an implementation I will have to look in every piece of code I'm pattern matching the type and add the new implementation). What would be the best approach to achieve this?
Thanks in advance!
Suppose you have these two (or more) repository implementations, which implement the same interface:
defmodule MyApp.Repository.Memory do
def get(key) do
# ...
end
def put(key, value) do
# ...
end
end
defmodule MyApp.Repository.Disk do
def get(key) do
# ...
end
def put(key, value) do
# ...
end
end
Then you can write a general repository module that will just forward the function calls to one of the repository backends, based on a configuration value in your config/config.exs file:
defmodule MyApp.Repository do
#backend Application.get_env(:my_app, :repository_backend)
defdelegate [get(key), put(key, value)], to: #backend
end
The configuration can be made so that it is environment specific (just look at the default config.exs in a mix project freshly created with mix new my_app):
# config/config.exs
import_config "#{Mix.env}.exs"
# config/dev.exs
config :my_app, repository_backend: MyApp.Repository.Memory
# config/prod.exs
config :my_app, repository_backend: MyApp.Repository.Disk
Throughout your entire code, you can then just use the MyApp.Repository module without explicitly referencing one of the specific implementations:
MyApp.Repository.put(:foo, "Hello world!")
value = MyApp.Repository.get(:foo)
My problem, simplified:
I have a dataGrid with a dataProvider "documents"
A column of the datagrid has a labelFunction that gets the project_id field of the document, and returns the project name, from a bindable variable "projects"
Now, I dispatch the events to download from the server the documents and the projects, but If the documents get downloaded before the projects, then the label function gives an error (no "projects" variable)
Therefore, I must serialize the commands being executed: the getDocuments command must execute only after the getProjects command.
In the real world, though, I have dozens of resources being downloaded, and those command are not always grouped together (so I can't for example execute the second command from the onSuccess() method of the first, because not always they must be executed together..)..
I need a simple solution.. I need an idea..
If I understand you correctly, you need to serialize the replies from the server. I have done that by using AsyncToken.
The approach: Before you call the remote function, add a "token" to it. For instance, an id. The reply from the server for that particular call will then include that token. That way you can keep several calls separate and create chains of remote calls.
It's quite cool actually:
service:RemoteObject;
// ..
var call:AsyncToken = service.theMethod.send();
call.myToken = "serialization id";
private function onResult(event:ResultEvent):void
{
// Fetch the serialization id and do something with it
var serId:String = event.token.myToken;
}