Class: Parse::LiveQuery::Subscription

Inherits:
Object
  • Object
show all
Defined in:
lib/parse/live_query/subscription.rb

Overview

Represents an active subscription to a LiveQuery. Manages event callbacks and subscription lifecycle.

Examples:

subscription = Song.subscribe(where: { artist: "Beatles" })

# Register callbacks using on() method
subscription.on(:create) { |song| puts "New song!" }
subscription.on(:update) { |song, original| puts "Updated!" }

# Or use shorthand methods
subscription.on_create { |song| puts "New song!" }
subscription.on_update { |song, original| puts "Updated!" }
subscription.on_delete { |song| puts "Deleted!" }
subscription.on_enter { |song, original| puts "Entered query!" }
subscription.on_leave { |song, original| puts "Left query!" }

# Error handling
subscription.on_error { |error| puts "Error: #{error.message}" }

# Connection events
subscription.on_subscribe { puts "Subscribed!" }
subscription.on_unsubscribe { puts "Unsubscribed!" }

# Cleanup
subscription.unsubscribe

Constant Summary collapse

@@id_monitor =

Class-level monitor for request ID generation

Monitor.new
@@request_counter =
0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client:, class_name:, query: {}, fields: nil, session_token: nil) ⇒ Subscription

Create a new subscription

Parameters:

  • client (Parse::LiveQuery::Client)

    the LiveQuery client

  • class_name (String)

    Parse class name

  • query (Hash) (defaults to: {})

    query constraints (where clause)

  • fields (Array<String>, nil) (defaults to: nil)

    specific fields to watch

  • session_token (String, nil) (defaults to: nil)

    session token for authentication



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/parse/live_query/subscription.rb', line 64

def initialize(client:, class_name:, query: {}, fields: nil, session_token: nil)
  @monitor = Monitor.new
  @client = client
  @class_name = class_name
  @query = query
  @fields = fields
  @session_token = session_token
  @request_id = generate_request_id
  @state = :pending
  @callbacks = Hash.new { |h, k| h[k] = [] }

  Logging.debug("Subscription created",
                request_id: @request_id,
                class_name: @class_name,
                query_keys: @query.keys)
end

Instance Attribute Details

#class_nameString (readonly)

Returns Parse class name being subscribed to.

Returns:

  • (String)

    Parse class name being subscribed to



44
45
46
# File 'lib/parse/live_query/subscription.rb', line 44

def class_name
  @class_name
end

#clientParse::LiveQuery::Client (readonly)

Returns the LiveQuery client.

Returns:



50
51
52
# File 'lib/parse/live_query/subscription.rb', line 50

def client
  @client
end

#fieldsArray<String> (readonly)

Returns fields to watch for changes (nil = all fields).

Returns:

  • (Array<String>)

    fields to watch for changes (nil = all fields)



53
54
55
# File 'lib/parse/live_query/subscription.rb', line 53

def fields
  @fields
end

#queryHash (readonly)

Returns the query constraints (where clause).

Returns:

  • (Hash)

    the query constraints (where clause)



47
48
49
# File 'lib/parse/live_query/subscription.rb', line 47

def query
  @query
end

#request_idInteger (readonly)

Returns unique request ID for this subscription.

Returns:

  • (Integer)

    unique request ID for this subscription



41
42
43
# File 'lib/parse/live_query/subscription.rb', line 41

def request_id
  @request_id
end

#session_tokenString? (readonly)

Returns session token for ACL-aware subscriptions.

Returns:

  • (String, nil)

    session token for ACL-aware subscriptions



56
57
58
# File 'lib/parse/live_query/subscription.rb', line 56

def session_token
  @session_token
end

Instance Method Details

#confirm!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Mark subscription as confirmed by server



229
230
231
232
233
234
235
# File 'lib/parse/live_query/subscription.rb', line 229

def confirm!
  @monitor.synchronize { @state = :subscribed }
  Logging.info("Subscription confirmed",
               request_id: @request_id,
               class_name: @class_name)
  emit(:subscribe)
end

#error?Boolean

Returns true if in error state.

Returns:

  • (Boolean)

    true if in error state



186
187
188
# File 'lib/parse/live_query/subscription.rb', line 186

def error?
  state == :error
end

#fail!(error) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Mark subscription as failed with error

Parameters:



240
241
242
243
244
245
246
247
# File 'lib/parse/live_query/subscription.rb', line 240

def fail!(error)
  @monitor.synchronize { @state = :error }
  error = SubscriptionError.new(error) if error.is_a?(String)
  Logging.error("Subscription failed",
                request_id: @request_id,
                error: error)
  emit(:error, error)
end

#handle_event(event) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handle an incoming event from the server

Parameters:



220
221
222
223
224
225
# File 'lib/parse/live_query/subscription.rb', line 220

def handle_event(event)
  Logging.debug("Handling event",
                request_id: @request_id,
                event_type: event.type)
  emit(event.type, event.object, event.original)
end

#on(event_type) {|object, original| ... } ⇒ self

Register a callback for a specific event type

Parameters:

  • event_type (Symbol)

    :create, :update, :delete, :enter, :leave, :error, :subscribe, :unsubscribe

Yields:

  • (object, original)

    block to call when event occurs

Returns:

  • (self)


91
92
93
94
95
96
97
98
# File 'lib/parse/live_query/subscription.rb', line 91

def on(event_type, &block)
  return self unless block_given?

  @monitor.synchronize do
    @callbacks[event_type.to_sym] << block
  end
  self
end

#on_create {|Parse::Object| ... } ⇒ self

Register callback for create events

Yields:

Returns:

  • (self)


103
104
105
# File 'lib/parse/live_query/subscription.rb', line 103

def on_create(&block)
  on(:create, &block)
end

#on_delete {|Parse::Object| ... } ⇒ self

Register callback for delete events

Yields:

Returns:

  • (self)


117
118
119
# File 'lib/parse/live_query/subscription.rb', line 117

def on_delete(&block)
  on(:delete, &block)
end

#on_enter {|Parse::Object, Parse::Object| ... } ⇒ self

Register callback for enter events (object now matches query)

Yields:

Returns:

  • (self)


124
125
126
# File 'lib/parse/live_query/subscription.rb', line 124

def on_enter(&block)
  on(:enter, &block)
end

#on_error {|Exception| ... } ⇒ self

Register callback for errors

Yields:

  • (Exception)

    the error that occurred

Returns:

  • (self)


138
139
140
# File 'lib/parse/live_query/subscription.rb', line 138

def on_error(&block)
  on(:error, &block)
end

#on_leave {|Parse::Object, Parse::Object| ... } ⇒ self

Register callback for leave events (object no longer matches query)

Yields:

Returns:

  • (self)


131
132
133
# File 'lib/parse/live_query/subscription.rb', line 131

def on_leave(&block)
  on(:leave, &block)
end

#on_subscribe { ... } ⇒ self

Register callback for successful subscription

Yields:

  • called when subscription is confirmed

Returns:

  • (self)


145
146
147
# File 'lib/parse/live_query/subscription.rb', line 145

def on_subscribe(&block)
  on(:subscribe, &block)
end

#on_unsubscribe { ... } ⇒ self

Register callback for unsubscription

Yields:

  • called when unsubscribed

Returns:

  • (self)


152
153
154
# File 'lib/parse/live_query/subscription.rb', line 152

def on_unsubscribe(&block)
  on(:unsubscribe, &block)
end

#on_update {|Parse::Object, Parse::Object| ... } ⇒ self

Register callback for update events

Yields:

Returns:

  • (self)


110
111
112
# File 'lib/parse/live_query/subscription.rb', line 110

def on_update(&block)
  on(:update, &block)
end

#pending?Boolean

Returns true if pending subscription confirmation.

Returns:

  • (Boolean)

    true if pending subscription confirmation



176
177
178
# File 'lib/parse/live_query/subscription.rb', line 176

def pending?
  state == :pending
end

#stateSymbol

Current subscription state

Returns:

  • (Symbol)

    :pending, :subscribed, :unsubscribed, or :error



83
84
85
# File 'lib/parse/live_query/subscription.rb', line 83

def state
  @monitor.synchronize { @state }
end

#subscribed?Boolean

Returns true if currently subscribed.

Returns:

  • (Boolean)

    true if currently subscribed



171
172
173
# File 'lib/parse/live_query/subscription.rb', line 171

def subscribed?
  state == :subscribed
end

#to_hHash

Returns subscription info as hash.

Returns:

  • (Hash)

    subscription info as hash



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/parse/live_query/subscription.rb', line 250

def to_h
  @monitor.synchronize do
    {
      request_id: request_id,
      class_name: class_name,
      query: query,
      state: @state,
      fields: fields,
    }
  end
end

#to_subscribe_messageHash

Build the subscription message to send to the server

Returns:



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/parse/live_query/subscription.rb', line 192

def to_subscribe_message
  msg = {
    op: "subscribe",
    requestId: request_id,
    query: {
      className: class_name,
      where: query,
    },
  }

  msg[:query][:fields] = fields if fields&.any?
  msg[:sessionToken] = session_token if session_token

  msg
end

#to_unsubscribe_messageHash

Build the unsubscribe message

Returns:



210
211
212
213
214
215
# File 'lib/parse/live_query/subscription.rb', line 210

def to_unsubscribe_message
  {
    op: "unsubscribe",
    requestId: request_id,
  }
end

#unsubscribeBoolean

Unsubscribe from this subscription

Returns:

  • (Boolean)

    true if unsubscribe message was sent



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/parse/live_query/subscription.rb', line 158

def unsubscribe
  @monitor.synchronize do
    return false if @state == :unsubscribed
    @state = :unsubscribed
  end

  Logging.debug("Unsubscribing", request_id: @request_id)
  client.unsubscribe(self)
  emit(:unsubscribe)
  true
end

#unsubscribed?Boolean

Returns true if unsubscribed.

Returns:

  • (Boolean)

    true if unsubscribed



181
182
183
# File 'lib/parse/live_query/subscription.rb', line 181

def unsubscribed?
  state == :unsubscribed
end