         return changed
 
     _save: (cb) =>
+        if @__is_saving
+            cb("already saving")
+        else
+            @__is_saving = true
+            @__save (err) =>
+                @__is_saving = false
+                cb?(err)
+
+    __save: (cb) =>
         if @_state == 'closed'
             cb?("closed")
-            return
-        if @_state != 'connected'
-            cb?("not connected")    # do not change this error message; it is assumed elsewhere.
             return
         # console.log("_save('#{@_table}')")
         # Determine which records have changed and what their new values are.

                dbg("success!")
                cb?()

    # Try to connect exactly once.  cb gets error if and only if fails to connect
    __try_to_connect_once: (cb) =>
        {no_sign_in, client, connect} = @_opts
        if no_sign_in
            # just need to be connected
            if client.is_connected()
                connect(cb)
            else
                client.once 'connected', (=> connect(cb))
        else
            # need to be signed in
            if client.is_signed_in()
                connect(cb)
            else
                client.once 'signed_in', (=> connect(cb))

class SyncTable extends EventEmitter
    constructor: (@_query, @_options, @_client, @_debounce_interval, @_cache_key) ->

        if @_id?
            @_client.query_cancel(id:@_id)
            @_id = undefined

        async.series([
            (cb) =>
                # 1. save, in case we have any local unsaved changes, then sync with upstream.
                if @_value_local? and @_value_server?
                    @_save(cb)
                else
                    cb()
            (cb) =>
                # 2. Now actually do the changefeed query.
                @_reconnect(cb)
        ], cb)

    _reconnect: (cb) =>
        dbg = @dbg("_run")
