Weave QuickStart Tutorial: The Weave is a non-trivial technology, and there are many things to learn before you can consider yourself competant. This tutorial takes you in easy steps through some basic operations so you can get started. Create a new Weave called `wv' ---------------------------- Weave clone wv Add a new item to the database. --------------------- ref=`wv newEvent` Items on the database are called a `events'. When you create a new event using `newEvent', it returns an internal reference which can be used to reference the event. Here, we have stored the reference in a shell variable $ref Reference the new item --------------- We now have exactly one item on our new database. We can reference it directly, like so: wv event $ref It also happens to be both the oldest and the newest event (since it is the only event), so we can also reference it like this: wv oldest wv newest Send the new item a message ------------- We send the item a message by appending the message to the commands used in the previous step. For example: wv oldest asText Adding data to the new item ------------------ Each item on the Weave is an Offsider, so it will respond to all the normal Offsider messages. Here are some examples: wv oldest description: I am the first event to be added to the Weave echo "No comment!" | wv newest attachment comment wv event $ref editMethod helloWorld wv event $ref asText Notice, however, that some standard Offsider methods are over-ridden by the Weave. `asText' is an example of this. Navigation - `after' and `before' ------------- First, add a whole lot of new items to the database: wv newEvent; wv newEvent; wv newEvent; wv newEvent; wv newEvent The first thing you should notice is that `wv newest'no longer refers to the original event (although `wv oldest' does). wv oldest asText wv newest asText Each event on the Weave has its own unique timestamp. These timestamps produce a natural chronological ordering for the events in the Weave. One way of navigating between events is to use this chronological order. For example: wv oldest after setKey name: foo wv newest before before before setKey name: bar One final thing about the timestamp is that you can actually provide the timestamp when you create an event. For example: wv newEvent 20020101_0101_00_123456.789000.0000 Even though this event was added after the very first one in our examples, as far as the Weave is concerned, it is the `oldest' event. Don't rely on `oldest' or `newest' except immediately after an event has been created. Using `fastList' to visit multiple events ---------------------- There is an event method called `fastList', which allows you to start at one event and then navigate to several other events, sending the same message to each event you come to. For example: wv oldest fastList after 3 asText wv newest before before fastList before all name The first argument for `fastList' is the direction to navigate. The second argument specifies how many events to visit, and the rest of the arguments provide the message to send to each event visited. Let's examine the last example in more detail. It breaks down like this: wv newest # start at the newest event on the Weave before before # navigate backwards in time two steps fastList before all name # send this message to that event. The message `fastList before all name' itself breaks down like so: fastList # the name of the method before # the direction to navigate all # keep going until you run out of events name # this is the message to send to each event. The final message `name' is normal Offsider syntactic sugar, and translates into the canonical message `getKey name' In fact, there is quite a bit of syntactic sugar happening in this example. If you want to see the fully expanded message, it looks like this: wv navigate newest navigate before navigate before fastList before all getKey name Thank goodness for syntactic sugar! Weave methods versus event methods --------------------- Notice also that the first `navigate' is a method on the Weave, whereas the other `navigate's are methods on individual events. In general, the Weave will understand a different set of methods to the events. To see this, do: wv methods wv newest methods wv event $ref methods wv allMethods | column wv newest allMethods | column wv event $ref allMethods | column Named events ------------- You can give an event a name, and then use that name to reference the event. This is not the same as providing the event with a key called `name', as we did in some earlier examples. For example wv newNamedEvent foo wv namedEvent foo name: baz wv namedEvent foo asText here we have created a named event with the name `foo'. But we have then given the event a key called `name', with the value of `baz'. The event's name is really `foo'. The named events are managed by a child dictionary of the Weave, called `namedEvents' (with an `s'). wv namedEvents pairs wv namedEvent foo Don't try and manipulate `namedEvents' directly unless you really understand what you are doing! Parent, child and sibling ----------------- The second form of navigation that the weave's events understand is heirarchical tree structures. These are created by designating some events as parents or children of others. Siblings are events that share a common parent. Examples: wv oldest isChildOfNamedEvent foo wv newest isParentTo $ref wv event $ref after isChildOf `wv event $ref before` wv namedEvent foo isParentTo `wv event $ref after` The types of navigation associated with these structures are: Navigate to a sibling, using `next' and `previous': wv oldest asText wv oldest next asText wv oldest next previous asText # should get you back to `wv oldest' Navigate to the parent: wv oldest parent asText Navigate to a child: wv namedEvent foo asText wv namedEvent foo oldestChild asText wv namedEvent foo newestChild asText wv namedEvent foo oldestChild next asText wv namedEvent foo newestChild previous asText Note that, whereas `after' and `before' respect the timestamp order, `next' and `previous' do not. You can mix and match the various navigation paradigms, although it will probably make no sense to do so! wv event $ref after parent oldestChild before asText The `null event' -------------- When you start navigating around inside the database, it is possible to specify a direction for navigation (for example `parent'), when that event doesn't have anything to navigate to (ie, it doesn't actually have a parent). In this case, you end up at an `event' called the `null event'. The null event is a real Offsider, but it is not a real event (it is actually a child dictionary of the Weave). Any attempt to navigate from the null event will just return you back to the null event. The null event will respond to a message `isNullEvent', so you can detect whether this situation has arisen: wv oldest isNullEvent returns empty string because this is NOT a null event. wv oldest before isNullEvent returns 'isNullEvent', because by definition there cannot be any event before the oldest one. wv oldest before after isNullEvent still returns 'isNullEvent', because once you reach the null event, you are stuck there! Arbitrary navigation --------------- In addition to these standard navigation directions, you can create your own. These act much like hypertext (http) links within a web page. You just create a link and point it to some other event. For example: # create and set a navigation key.. wv namedEvent foo setNavigation gotoRef $ref # navigate using that navigation key.. wv namedEvent foo gotoRef asText Here we have set up a navigation from the named event `foo'. The navigation `key' is `gotoRef', and it points to the event with reference $ref. Note that we have not specified a return navigation. We can do that like this: wv event $ref setNavigation gotoFoo `wv namedEvent foo` wv event $ref gotoFoo asText You can give the navigation key any name you like. Don't give it any of the standard names (like `after', `parent', `next'), though, because the results can be unpredictable. When setting up these ad-hoc navigations, it is sometimes safer to avoid syntactic sugar, and use: wv event $ref navigate gotoFoo The reason is that if you try to do an arbitrary navigation like wv event $ref foo asText where the event `wv event $ref' doesn't actually have a navigation key `foo', then the event cannot tell that you are trying to navigate, and will think that you are trying to either invoke a method, or trying to access a key. Either way the results can be unexpected! If you use the fully expanded version, wv event $ref navigate foo asText you will see that you end up at the null event, which is able to handle the message a little more sensibly. Using the QueueReader ---------------- All of the examples I have given will work, but for a production system, there is something more that you should consider. If more than one user tries to create an event at the same time, or modify the navigation keys, then there is a real danger that the database will become corrupted. The way to prevent this is to make sure that all database updates get sent through the Weave's QueueReader. Each Weave comes with its own QueueReader. The default action of this QueueReader when it processes a request from its queue is to just send the entire request through to the Weave as a message. Therefor, the Weave's QueueReader can be used to make sure that database updates get done in an orderly, sequential manner, thus preventing data corruption. For example, instead of going: wv event $ref value: 10 you could go: wv QueueReader queue event $ref value: 10 The following message is equivalent: wv queue event $ref value: 10 The Weave method `queue', is just a wrapper for `QueueReader queue'. To make sure that these requests get processed, you need to `activate' the QueueReader. The suggested way to do this is: wv QueueReader start Look at the QueueReader documentation for further details about QueueReader methods. To create a new event, you can go: wv queue newEvent but you can't then tell what the event's reference is. Instead, you should use id=`wv queueNewEvent` This will return an `event id' (which is not the same as an event reference). You can then wait for the event to come into existence: wv waitForEventId $id which will block, waiting for the event to be created. Once the event has been created, you can get its reference by doing: ref=`wv id2ref $id` When to use the QueueReader ------------------- It is often a matter of choice whether to use the QueueReader or not. Some important uses for the QueueReader are: 1. to prevent database corruption by making sure that updates are performed sequentially. 2. to improve interactive response by queueing time-consuming updates so they are effectively placed in `the background', to be performed at some later time. 3. to provide an audit trail, a record of what was changed and when. Typically you would not use the QueueReader to do data requests, since there is no danger of data corruption (and anyway, it is not easy to get the result of the data request!). If you write a method that does a whole lot of individual but related data updates, then you might queue the method call, but within the method there is no need to queue all the individual updates because you already have the database to yourself. It is usually not neccessary to queue a request to update a single event key, or an event attachment, because even if two users are updating at the same time, the final result will be correct. A good situation to queue requests is when you are setting several navigation keys, and you want them all to be consistent. Thus operations like `isChildOf', `orphan', `removeEvent' and so on are prime candidates for queueing. As mentioned before, there is a special method (`queueNewEvent') for queueing the creation of a new event. In Summary ---------------- As you can see, there is quite a lot to learn. If you are pretty smart, I would expect that you will need to set up maybe four or five Weaves AND use them for some practical purpose before you could consider yourself competant. So ... what are you waiting for? cheers, Glen