Run Data Persistence Implementations

This is a page to clarify how to implement a run generated data store. That term was just made up for this page, if there is better way to describe this let me know.

The main interface to implement is

net.sf.sail.core.beans.service.AgentService

I Scott Cytacki am working on this. I'm not committing things because I'm trying to work out as many issues at once so the commited code doesn't go through convulsions.

Updated uncommited AgentService

public interface AgentService {
	public ISock getSock(Rim rim, IAgent agent) throws UnsupportedRimShapeException;

	public AgentSet getAgentsInRole(Role role);

	IAgent createAgent(Role role);

	AgentSet getAgentsOfUser(User user);

	public void dump(SessionContext session, PrintStream out);
}

There are two implementations of this interface:
net.sf.sail.common.persistance.memory.MemoryPersistenceImpl
and
org.telscenter.pas.db.JdbcPersistence

I'm working on a third:
net.sf.sail.emf.sailuserdata.EMFPersistenceManager

ISock and SockEntry

The sock and sockEntry are tricky. A sockEntry is contained by and created during a session. However the access to this sockEntry is typically through a sock. This access is done at runtime or by a report. However the "sock" view of sock entries might be incomplete if there is a disconnected session occuring. In the data model the sock does not maintain its own list of sock entries. Thinking in terms of containment, this means the sock entries are contained by the session, not the sock. However this means in order to access the sock entries all previous sessions that contain sock entries for this sock need to be available. One filter for these sessions is their AgentSet: every previous session that has an agent that is currently active. ISock becomes a view/query on the datamodel that finds all the sock entries for the sock and orders them.

Ideally the persistence layer doesn't need to worry about this ISock view. It makes sense for the persistence layer to be able optimize this ISock view, but that doesn't need to be a requirement. So the SAIL framework can provide a default implemenation of this view, based on simpler interfaces that the persistence layer needs to implement.

This relationship of Sessions, Socks, and SockEntries provides a way to talk about offline user data. How it will be merged, how it is possible to know which userdata is needed before going offline.

Session and Agents

The AgentService needs to track the active agents. This is because when the getAgentsInRole() or getAgentsOfUser() methods are called, one intention is to return the set of agents in the current session in that role. But it might also be that getAgentsOfUser should return dynamic agents that were created in previous groups. This currently isn't reflected in the data model. In the model agents are only linked to the Offering. There will be lots of agents in the offering (groups of users sitting at different computers at different times).

Another way to think about this is: where should the agent be stored when createAgent(Role) is called. It should be stored in the Offering. But it needs to also at least be stored by the AgentService internally. And in that case it should be saved as part of the data about the Session.

It might be easiest to differ a solution to this until the emf implementation is work. Because it should make visible and concrete the different contexts in which agents, users, and roles are used.

Next question is about Agent consistency: Can there be more than 1 agent with the same set of users and the same role in the one offering?
This comes up when thinking about how to implement the createAgent method. Currently it doesn't have enough info to make sure the Agent's users and role is unique. In the offline case it will be impossible to prevent more than one agent with the same set of users. For example if all the computers are offline, and a group of users moves from one computer to another and restarts. There will now be two identical agents created in the offering.

Service name and design

The current name of the service is AgentService. I think RunPersistenceService would be better, or OfferingPersistenceService would be better.

Currently there are 2 interfaces:
AgentService and SessionService. There are two users of these interfaces. Persistence implmentors, and Pod implementors.

From a Pod implementor point of view the distinction between the 2 seems arbritary (at least to me)
From a Persistence implementor, and from the SAIL Framework's point of view, the distinction is to separate functionality:

  1. functionality that could be provided by a generic non SAIL aware Portal
  2. functionality that is specific to the SAIL model saving user data.

One idea is to create two separate sets of interfaces. Those for persistence implementors, and those for Pod implementors. And there will be a thin layer provided by the SAIL framework for glueing these two sets of interfaces together. A few issues it would clean up:

  1. User - UserUuuid
    • Persistence implementors shouldn't be distracted by User objects only the UserUuid is important.
    • Pod implementors shouldn't need to worry about UserUuid's. They can just deal in User objects.
  2. SessionService.addUser - SessionService.removeUser
    • this should not be available to Pod implementors
  3. The Session functionality is combined with the Portal like functionality, so there is not a clear set of interfaces that a need to be implemented to connect the SAIL runtime with a new portal. (I'm not sure about this one, it just seems that way from what currently understand)

IAgent Questions

Both of these implementions also provide an implementation of IAgent. And they assume all the IAgent objects being passed in are instances of their implementation.

Where do these IAgents come from? - from the AgentService.
Is it correct that implementations can assume they will only get instances of their IAgent implementation? - Yes, that's correct.

So only one AgentService implementation can be in the ClassLoader of the pod? - Yes.

Can activities (pod beans) create Agents on the fly? - Yes, by a call to the current AgentService. This is necessary in order to allow dynamic group creation.

If IAgent's deal in UserUuid's it will be inconvenient for Pod implementors to work with them, if they want to get a list of the current users, or to set up users. But this might be easy to provide help for.

Return values

getAgentsOfUser() and getAgentsInRole() always return a valid AgentSet. It may be empty but never null.

If the user or role does not exist, an exception is thrown.

  • In the preview curnit class the IAgent is created using hard coded roles and users.
  • The cases agents are created in reponse to calls to getAgentsOfUser and getAgentsInRole.

User Questions

AgentService deals only in UserUuid, the SAIL concept of a user.

The SessionDataService handles "real users", which are in the context of a session provided by a portal (or something like that).

The learning environment cannot create Users or new UserUuids.

For now, equals() is required to check equality. We may use internning later to make == work.

Multiple Data Stores at one time

Q. Do we need to allow clients of the AgentService access to 2 different instances at the same time?
A. No. A client only gets one AgentService. It might be that that service sends the data into to 2 hidden rims at the same time, for example a network based rim and a local cached rim.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.