View
 

DataStore-About Records

Page history last edited by Byron Ruth 3 mos ago

Now that you’ve defined your data model and added some test fixture data, its time to get started working with individual records. This section covers the in-depth background about how records work. The next section will go in-depth on how to use them.

 

Anatomy of a Record

 

The DataStore framework is designed to handle large amounts of data. To support this, records are designed to be very lazy.  When you load data into the store, no record instances are created until you actually try to access an individual data hash. Once the record is created, it won’t access your data hash until you try to access properties on them.

 

Lazily building records like this makes the DataStore framework very fast; especially when loading large amounts of data. However, it does make working with Records slightly more complicated as well. That’s why it is important to understand how records actually work internally.

 

All records have two basic elements that they manage: a data hash and a status. The data hash is the actual data you add to the store. The status is used to keep track of where the record is in the overall life cycle. Since records may not be materialized until you actually ask for them, the data hash and status for a record is actually kept in the store, identified by a unique store key.

 

Store keys are simple integers that are assigned to hashes as they are loaded into the store. They are transient and mostly for internal use; you should never save them to a server or even expect them to remain constant across reloads.

 

Records themselves are only instantiated (or “materialized”) when you first try to access the them. When records are created, they only have two elements: the owner store and the storeKey. Only when you access properties on the record will it take the time to map this store key back to a data hash and status to return the correct value to you.

 

Usually you won’t need to access the storeKey or store properties directly when working on records. Instead you should use the higher level attribute helpers and access the contents of your model. Just keep in mind that internally the record is simply a pointer to data that is actually living in a store. This is why it is so important to use get() and set() to access all public properties.

 

 

Record States

 

All records generally have a life cycle as they are created or loaded into memory, modified, committed and finally destroyed.  This life cycle is managed by the status property on your record. 

 

The status of a record is modelled as a finite state machine.  Based on the current state of the record, you can determine which operations are currently allowed on the record and which are not.

 

Primary States

 

In general, a record can be in one of five primary states, shown in the state chart below.  All of these states are defined as constants on SC.Record.

 

 

SC.Record.EMPTY

This defines a store key that has not yet been assigned to a store key.  You should never get a Record instance with this status, though you might encounter it if you use the low-level data hash API instead.

 

SC.Record.BUSY

A record is busy when the store has asked the data source to load or commit changes to the server.  While in this state, your record cannot be modified.  Usually you will encounter this state when you first retrieve a record before the server has returned with the initial data.

 

SC.Record.READY

Once a record has loaded its initial data and can be modified by the store, it will be in the READY state.  While in this state you can modify properties.  Most records will spend most of their time in this state.

 

SC.Record.DESTROYED

Records only enter this state once you have destroyed them.  A record in the destroyed state cannot be modified obviously.  It will also usually never leave this status, though the data source could always choose to revive the record if needed.

 

SC.Record.ERROR

This state only occurs if the data source indicates that it encountered an error while loading the record.  The record cannot be modified in this state.  To leave this state, the data source will need to change it.

 

Ready Substates

 

A record that is in the READY state may be in one of three substates.  These states determine what operations you can perform on the record.

 

 

SC.Record.READY_NEW

A record in this state was created in memory but has not yet been committed back to the server.  If you commit changes on your store, this record will be sent to the data source automatically.  Likewise if you destroy this record it will simply be removed from memory without notifying the server.  

 

The data source also cannot modify records while they are in this state since they have local changes that would be lost.

 

SC.Record.READY_CLEAN

This is the default state of a record once it has been loaded from the server or it its changes were committed.  A record in this state exists on the server and has not been modified locally.  

 

If you commit changes on your store, this record will NOT be included in the list of records sent to the server.  Likewise, if your data source receives notification from the server that this record has changed, it can modify this record without any kind of error since no changes would be lost.

 

SC.Record.READY_DIRTY

This is the state of a record that exists on the server but has since been modified in memory.  It has pending changes that will be sent to the server when you commit changes in your store.

 

If your data source tries to modify this record, it will throw an error since local changes would be lost.

 

Destroyed Substates

 

A record in the DESTROYED state may have one of two substates.  Note that you cannot modify a record once it is in any DESTROYED state.  Also destroying an already destroyed record will have no effect.

 

 

SC.Record.DESTROYED_CLEAN

A record in this state has been destroyed both in memory and on the server.  A record enters this state, for example, if your data source destroys the record or if you destroy the record in memory then commit that change successfully to the server.

 

SC.Record.DESTROYED_DIRTY

A record in this state was destroyed in memory by the application, but it has not yet been destroyed on the server.  A record in this state cannot accept changes from the server unless the server also puts it into a destroyed state.  

Committing changes on your store will send ask the data source to send this destroy to the server.

 

Busy Substates

 

A record in a busy substate is essentially waiting on the data source to complete some action.

 

Note that the busy state is simply an indicator that the store has sent some changes on this record to the data source and its waiting on the data source to give its OK before more changes are allowed.  Depending on the data source implementation, you may never see a record in a busy state.  For example, fixtures immediately clear busy record since they don’t need to wait for a server round trip.  

 

While the record is in a busy state it cannot be modified in memory.

 

 

SC.Record.BUSY_LOADING

When you first get a record from the store, it will usually be in the BUSY_LOADING state.  This means that the record did not exist in memory and the server has not yet returned any data.  All properties will be empty at this point.

When data is loaded for this record, it will transition to READY_CLEAN.

 

SC.Record.BUSY_CREATING

A record in this state was newly created in memory.  We are not waiting on the data source to confirm that it has been created in the server as well.  Once this completes, the record will become READY_CLEAN.  If the create fails, the record will return to READY_NEW.

 

SC.Record.BUSY_COMMITTING

A record in this state was modified in memory and it is waiting on the data source to confirm the change is saved on the server as well.  Once this completes, the record will become READY_CLEAN.

 

SC.Record.BUSY_REFRESH_DIRTY

A record in this state has local changes but you asked the data source to reload the data from the server anyway.  When the server updates, it will replace any local changes with a fresh copy from the server.  If the refresh fails, the record will return to its READY_DIRTY state.

 

SC.Record.BUSY_REFRESH_CLEAN

A record in this state has no local changes but you asked it to reload the data from the server anyway.  When the server finished, success or failure, this record will return to the READY_CLEAN state (unless there is an error).

 

SC.Record.BUSY_DESTROYING

A record in this state was destroyed in memory and now is being destroyed on the server as well.  Once the destroy has completed, the record will become DESTROYED_CLEAN.  If the destroy fails (without an error), it will become DESTROYED_DIRTY again.

 

How to Determine the Record State

 

Records can be in one of five primary states with several substates in each category.   These states are stored as an integer mask on the status property while their associated constants are stored on SC.Record.  To determine if a record is in a given state, you should always use an logical AND mask.  

 

For example, to test that a record is in the READY top-level state, you would use code like this:

 

if (record.get(‘status’) & SC.Record.READY) {

  // is ready

} else {

  // is NOT ready

}

 

 Note the single ampersand.   This will return true if the status is in any kind of ready state, no matter the substate.

 

Moving On 

 

Continue to learn how to Use Records »

or go back to DataStore Programming Guide Home »

 

Comments (0)

You don't have permission to comment on this page.