<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="374368" data-post-id="374368">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi <a class="mention" href="/u/kingdomcoder" rel="nofollow">@kingdomcoder</a>,</p>
<p>Thanks for the thoughtful response! I really appreciate the detailed API suggestions.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="23" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p>I think of PubSub in Hologram the same way I think of events—they’re triggers (that sometimes carry data). These server-side “events” can be similarly bound to actions/commands, and the rest of the Hologram plumbing immediately becomes available to us. I imagine new server-side functions <code>put_pubsub</code> and <code>delete_pubsub</code> as the main additions.</p>
</blockquote>
</aside>
<p>I definitely think about this in a similar way - actions and commands could be pubsub message handlers. This feels like a natural extension of the existing patterns.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="23" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<h3>Add a Subscription</h3>
<p>To subscribe to a PubSub channel, call <code>put_pubsub</code> in <code>init/3</code> or <code>command/3</code>:</p>
<p><code>put_pubsub(server, pubsub_channel, command: :my_command)</code></p>
<p>or</p>
<p><code>put_pubsub(server, pubsub_channel, action: :my_action)</code></p>
<h3>Delete a Subscription</h3>
<p>To unsubscribe from a PubSub channel, call <code>delete_pubsub</code> in <code>command/3</code>:</p>
<p><code>delete_pubsub(server, pubsub_channel)</code></p>
<p>or</p>
<p><code>delete_pubsub(server, pubsub_channel)</code></p>
<p>I suggest there should also be a cleanup mechanism that unsubscribes when a component is removed from the page.</p>
</blockquote>
</aside>
<p>I like the idea of something similar to <code>put_pubsub</code>/<code>delete_pubsub</code> approach, and I think there should be a possibility to subscribe/unsubscribe dynamically. But shouldn’t there be some component/page level DSL for that, so that the subscribing and unsubscribing is handled automatically (declaratively instead of imperatively)? I’m thinking about lifecycle management - it would be nice if developers didn’t have to manually track and clean up subscriptions in most cases.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="23" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p>Additionally, I don’t think PubSub handling should be restricted to pages. This is one of the banes I have with LiveView where <code>handle_info</code> is available only in the LiveView and not in LiveComponents. Each component should be able to call <code>put_pubsub</code> and <code>delete_pubsub</code> in its own <code>init/3</code> and <code>command/3</code> functions.</p>
</blockquote>
</aside>
<p>Yeah, absolutely. Pages are basically a special case of components, so this will be available in any page or stateful component (one that has a cid). No reason to artificially restrict this capability.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="23" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p>Finally, I wouldn’t recommend adding a <code>target</code> option to <code>put_pubsub</code> where a subscription in one page/component can trigger a command or action in another. Each page/component should subscribe independently to a channel if it needs to react to messages. This is not a “hard” suggestion, but I think it will help avoid confusion.</p>
</blockquote>
</aside>
<p>I can agree with that approach for general pub/sub. Though I think we need a way to send targeted messages - e.g., when a background job is finished and needs to notify a specific user session or component. Using pub/sub semantics for that would be too much overhead/boilerplate. I’d like better semantics for that use case - maybe something more direct than the broadcast model.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="23" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p>PS: Thank you for always welcoming input from the community. We’re grateful for your hard work <img src="https://forum.elixirforum.com/images/emoji/apple/clap.png?v=15" title=":clap:" class="emoji" alt=":clap:" loading="lazy" width="20" height="20"> <img src="https://forum.elixirforum.com/images/emoji/apple/clap.png?v=15" title=":clap:" class="emoji" alt=":clap:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Thank you! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374368" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-374368" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374368"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #31"></div>
  </section>
</div>
    <div class="postbit" id="374384" data-post-id="374384">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jam" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/120/36266_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jam
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>actions and commands could be pubsub message handlers</p>
</blockquote>
</aside>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But shouldn’t there be some component/page level DSL for that, so that the subscribing and unsubscribing is handled automatically (declaratively instead of imperatively)? I’m thinking about lifecycle management - it would be nice if developers didn’t have to manually track and clean up subscriptions in most cases.</p>
</blockquote>
</aside>
<p>Yes 100% to both of these.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374384" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-374384" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374384"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #32"></div>
  </section>
</div>
    <div class="postbit" id="374419" data-post-id="374419">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But shouldn’t there be some component/page level DSL for that, so that the subscribing and unsubscribing is handled automatically (declaratively instead of imperatively)? I’m thinking about lifecycle management - it would be nice if developers didn’t have to manually track and clean up subscriptions in most cases.</p>
</blockquote>
</aside>
<p>I would strongly caution against getting caught up at the wrong level of abstraction here. You should be thinking about how to provide users with declarative APIs for managing <em>any</em> type of resource, not just PubSub subscriptions. If you have the former the latter becomes a natural extension.</p>
<p>Look at how React evolved from lifecycle callbacks to hooks with cleanup functions. <a href="https://acko.net/blog/climbing-mt-effect/" rel="noopener nofollow ugc">This article provides a more detailed take on the topic</a> (see the “Strange Effects” section in particular). Note that the author has in his own work adopted this paradigm to interface with graphics APIs (which are some of the worst APIs ever written).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374419" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-374419" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374419"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #33"></div>
  </section>
</div>
    <div class="postbit" id="374422" data-post-id="374422">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Eiji" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Eiji/120/36743_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Eiji
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But shouldn’t there be some component/page level DSL for that, so that the subscribing and unsubscribing is handled automatically (declaratively instead of imperatively)? I’m thinking about lifecycle management - it would be nice if developers didn’t have to manually track and clean up subscriptions in most cases.</p>
</blockquote>
</aside>
<p>The first rule with macros (and therefore DSL) is to not use them unless they are really needed. If we are going to let developer do this by hand (which is important in complex cases like tabbed pages) then there is really no need to duplicate the feature and introduce new <code>DSL</code>. Said macro would need to have some unique feature or use case.</p>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>I can agree with that approach for general pub/sub. Though I think we need a way to send targeted messages - e.g., when a background job is finished and needs to notify a specific user session or component. Using pub/sub semantics for that would be too much overhead/boilerplate. I’d like better semantics for that use case - maybe something more direct than the broadcast model.</p>
</blockquote>
</aside>
<p>It’s also important to mention that depending on case people may want to start pub/sub on both server and/or client and send data from server to client or from client to server. I believe in games (validated messages coming from trusted source) it may be important i.e. pub/sub logic may be happening on server while game logic (like drawing) would happen on client). <img src="https://forum.elixirforum.com/images/emoji/apple/+1.png?v=15" title=":+1:" class="emoji" alt=":+1:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="garrison" data-post="34" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>I would strongly caution against getting caught up at the wrong level of abstraction here. You should be thinking about how to provide users with declarative APIs for managing <em>any</em> type of resource, not just PubSub subscriptions. If you have the former the latter becomes a natural extension.</p>
</blockquote>
</aside>
<p>I fully agree with that. We definitely need some low-level API for sending commands and actions especially if we talk about background processes. Pub/sub may use such low-level API too. <img src="https://forum.elixirforum.com/images/emoji/apple/+1.png?v=15" title=":+1:" class="emoji" alt=":+1:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374422" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-374422" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374422"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #34"></div>
  </section>
</div>
    <div class="postbit" id="374514" data-post-id="374514">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="kingdomcoder" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/120/24667_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  kingdomcoder
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hey, Bart</p>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>I like the idea of something similar to <code>put_pubsub</code>/<code>delete_pubsub</code> approach, and I think there should be a possibility to subscribe/unsubscribe dynamically.</p>
</blockquote>
</aside>
<p>You nailed it here on the dynamic subscription. I recently had that use case: initially subscribe to a specific livestream, dynamically subscribe/unsubscribe to live chat messages when the livestream starts/stops.</p>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>But shouldn’t there be some component/page level DSL for that, so that the subscribing and unsubscribing is handled automatically (declaratively instead of imperatively)?</p>
</blockquote>
</aside>
<p>I love this. If the state is available, a declarative solution can work. I can imagine something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">subscribe topic, opts
subscribe topic, condition, opts

# where:
# - topic -&gt; string
# - condition -&gt; boolean
# - options:
#   - action: :my_action
#   - command: :my_command
#   - target: "string"
#   - delay: milliseconds


# e.g.
subscribe "my-topic", action: :my_action
subscribe "room:#{@room_id}", action: :update_messages
subscribe "#{@birthdays_feed_id}", @open_to_invites == true, command: :add_to_calendar
subscribe "user-joined-#{@group_id}", action: :run_cool_animation, target: "layout", delay: 500

# in my use case
subscribe "#{@streaming_account_id}", action: :handle_stream_event
subscribe "chat-#{@live_chat_id}", @stream_status == :live, action: :update_live_chat
</code></pre>
<p>Is this the approach? <a class="mention" href="/u/bartblast" rel="nofollow">@bartblast</a></p>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Though I think we need a way to send targeted messages - e.g., when a background job is finished and needs to notify a specific user session or component. Using pub/sub semantics for that would be too much overhead/boilerplate. I’d like better semantics for that use case - maybe something more direct than the broadcast model.</p>
</blockquote>
</aside>
<p>I can definitely see the case here for targeted messages. I guess it will be useful for messaging in a broader sense beyond pubsub.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374514" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-374514" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374514"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #35"></div>
  </section>
</div>
    <div class="postbit" id="374515" data-post-id="374515">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Eiji" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Eiji/120/36743_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Eiji
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="kingdomcoder" data-post="36" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p>I love this. If the state is available, a declarative solution can work. I can imagine something like:</p>
</blockquote>
</aside>
<p>It’s good and bad …</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="36" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">subscribe topic, opts
subscribe topic, condition, opts
</code></pre>
</blockquote>
</aside>
<p>Yup, those clauses would handle most of use cases if not all (assuming that all communication goes through actions and commands).</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="36" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<p><code># - condition -&gt; boolean</code></p>
</blockquote>
</aside>
<p>Nope, it needs to be a quoted expression which evaluates to boolean. This is important since such quoted expression needs to be unquoted somewhere and <code>Hologram</code> does not uses custom <code>def</code> or <code>action</code> and <code>command</code> DSL which means there would be lots of extra work, breaking changes and decrease of flexibility since it’s not easy in <code>Elixir</code> to override same function multiple times, so it could potentially break any existing <code>def</code> overrides.</p>
<aside class="quote no-group" data-username="kingdomcoder" data-post="36" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kingdomcoder/48/24667_2.png" class="avatar"> kingdomcoder:</div>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">subscribe "#{@birthdays_feed_id}", @open_to_invites == true, command: :add_to_calendar
</code></pre>
</blockquote>
</aside>
<p>That’s long …</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">params.open_to_invites &amp;&amp; subscribe(server.state.birthdays_feed_id)
</code></pre>
<p>Also we have to answer those questions:</p>
<ol>
<li>How do you deal with <code>params</code> and <code>client/server</code> states in <code>DSL</code>?</li>
<li>How to avoid confusion with module attributes?</li>
</ol>
<p>Developers already use at character (<code>@</code>) in templates and they are just used to it, but <code>DSL</code> is completely different topic. Many <code>DSL</code> supporting using module attributes and this would be <strong>extremely</strong> confusing. It would be the most commonly known gotcha in <code>Hologram</code>.</p>
<p>Doing that without <code>DSL</code> becomes simple and much more clear solution, so many people would have all rights to say that using <code>DSL</code> is rather a bad practice. That’s exactly why I said that without a really good reason we shouldn’t force it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374515" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-374515" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374515"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #36"></div>
  </section>
</div>
    <div class="postbit" id="374616" data-post-id="374616">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="Eiji" data-post="26" data-topic="72519" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<aside class="quote no-group" data-username="bartblast" data-post="25" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>I’m definitely considering different approaches here.</p>
</blockquote>
</aside>
<p>I would say that <strong>at least for now</strong> you should go the “safe way” and implement <code>Pub/Sub</code> that is very similar to the <code>phoenix</code> one. Of course some framework-related things have to be adjusted (actions vs <code>handle_*</code> functions), but I would rather stay with <strong>similar</strong> naming concept simply to make migrating existing applications to <code>Hologram</code> as simple as possible.</p>
<p>I think that’s fastest way, best for initial adoption and does not block possible alternative solutions in future. Maybe a good point would be to release it as <code>hologram_pubsub</code>, so it’s not considered as a part of the <code>core</code> and could be easily replaced only by updating generators (if any) and guides.</p>
</blockquote>
</aside>
<p>I understand the appeal of the “safe” approach, but copying Phoenix’s pubsub patterns mainly for familiarity is a dead end IMO. Whatever we ship becomes something I need to maintain long-term, and building on borrowed design decisions that don’t fit Hologram’s architecture creates technical debt from day one.</p>
<p>The migration story isn’t really about API similarity anyway. Pub/sub has a small surface area - you subscribe to topics, handle incoming messages, and maybe do some authorization. The specific function names matter less than getting the core patterns right. Whether someone calls <code>Phoenix.PubSub.subscribe/2</code> or <code>put_pubsub/3</code>, they’re still just expressing “listen to this topic and run this code when messages arrive.”</p>
<p>I’d rather spend the extra design time upfront to create something that fits naturally with Hologram’s component model and action/command patterns. The migrations will be straightforward regardless since the conceptual mapping is simple.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374616" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-374616" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374616"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #37"></div>
  </section>
</div>
    <div class="postbit" id="374618" data-post-id="374618">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="27" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>First of all I want to be very clear that your vision is <em>much</em> more important than mine. Hologram is your project and you have a better idea of where you want it to go than I do. And at the end of the day I am a programmer too; if I want a framework built a certain way, I can do it myself. No excuses there.</p>
<p>I only want you to consider my feedback if it’s something you <em>haven’t thought of</em>. If you disagree with me then don’t worry about it!</p>
</blockquote>
</aside>
<p>You’re absolutely right that it starts with my vision - I do have ideas about where I want Hologram to go. But it would be a big mistake for me not to listen to feedback from others along the way. If I only built for my own specific vision, I’d end up creating a framework tailored to just one version of myself and my particular use cases.</p>
<p>I’ve got limitations - including ones I’m not even aware of - and my perspective is naturally limited to what I’ve been exposed to. The experiences you’ve shared and your perspective on these trade-offs are genuinely helpful as I think through this. Because of that, I really value you sharing your vision and perspective, even though I don’t agree with some of them. But I’m definitely open to changing my mind! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group quote-modified" data-username="garrison" data-post="27" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<aside class="quote no-group" data-username="bartblast" data-post="25" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>I’m thinking particularly about high-frequency or ephemeral events - like cursor tracking in a collaborative drawing app, typing indicators, or even simple toast notifications.</p>
</blockquote>
</aside>
<p>So first of all, yes there are <em>some</em> things which really are ephemeral. And no, I don’t think I would run cursor positions through the database.</p>
<p>But I don’t think I would run them through PubSub either. For one, architecturally this means sending all messages to all nodes in order to get them to the right user, when really you would want to send all users to one node. Unless you really have <em>massive</em> fanout.</p>
</blockquote>
</aside>
<p>I don’t think it’s entirely accurate that Phoenix PubSub “sends all messages to all nodes in order to get them to the right user.” Phoenix PubSub maintains awareness of which nodes have active subscriptions to which topics. When you broadcast to a topic, the message is only sent to nodes that have at least one process subscribed to that topic - not to all nodes in the cluster. Each node maintains a local registry of which processes are subscribed to which topics, and nodes communicate subscription information to each other so they know the topology of who’s interested in what.</p>
<p>In Hologram’s case, this could work well since Hologram clients (with their unique connection IDs) could act as nodes in this distributed system - each maintaining their own subscription state and participating in the routing topology.</p>
<aside class="quote no-group" data-username="garrison" data-post="27" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>But also, topic-based PubSub is a very blunt tool. Apps with rich functionality have complex requirements which are difficult to express this way. I mean, what if I want to send a subset of cursors to a subset of users? If you have a passing familiarity with WebRTC you know this is <a href="https://hexdocs.pm/ex_webrtc/0.15.0/simulcast.html#switching-between-simulcast-encodings" rel="noopener nofollow ugc">far from a hypothetical</a>, even in relatively simple cases.</p>
</blockquote>
</aside>
<p>You raise a valid point about complex routing requirements like “subset of cursors to subset of users.” But that feels more like an argument for having richer topic semantics rather than abandoning the pub/sub model entirely. Topics could be hierarchical, pattern-based, or support more sophisticated matching - similar to how message brokers like RabbitMQ handle complex routing.</p>
<aside class="quote no-group" data-username="garrison" data-post="27" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>What I would probably do is embrace OTP and create a “room” abstraction (a server process) which sends/receives messages to clients. Note that this is not PubSub because <em>there is no fanout</em>. I would then store the location of said process (the node in a distributed setting) in the database as well as whatever else is needed to look it up (maybe the name of the room).</p>
<p>Then I could implement the room as a GenServer or whatever that sends and receives the ephemeral data. In the limit you could imagine this functioning like a game server. Actually, it may be helpful to reason about what would happen if you tried to build a game server using PubSub.</p>
</blockquote>
</aside>
<p>Interesting idea… but I wonder if it’s essentially solving the same fundamental problems that Phoenix PubSub already handles:</p>
<ul>
<li>Discovery: How do you find the right GenServer? (topic-based routing)</li>
<li>Distribution: What if the GenServer is on a different node? (distributed registry)</li>
<li>Failure handling: What if the GenServer crashes? (automatic cleanup)</li>
<li>Scalability: What if you have thousands of rooms? (efficient ETS-based lookups)</li>
</ul>
<p>Phoenix PubSub provides battle-tested solutions for exactly these challenges. The GenServer approach would need to reimplement much of this infrastructure.</p>
<aside class="quote no-group quote-modified" data-username="garrison" data-post="27" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<aside class="quote no-group" data-username="bartblast" data-post="25" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>And practically speaking - if we’re tracking cursor positions today and want to add pressure sensitivity tomorrow, wouldn’t we need database migrations for what’s essentially transient data?</p>
</blockquote>
</aside>
<p>I think this is orthogonal. You could just as easily store unstructured data in a database. Alternatively you could design a schema migration system that is actually good (I’m doing this too).</p>
</blockquote>
</aside>
<p>I think we might be looking at different layers here. As I mentioned earlier in the thread, pub/sub is a messaging primitive - useful for the cases where its semantics make sense (ephemeral events, notifications, real-time updates where eventual consistency is acceptable). It’s not meant to be the foundation for all data synchronization, just a tool in the toolkit.</p>
<p>Your database-centric approach makes perfect sense for stateful, consistent data. But I still see value in having both patterns available, with clear guidance on when to use which.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374618" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-374618" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374618"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #38"></div>
  </section>
</div>
    <div class="postbit" id="374620" data-post-id="374620">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="39" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>When you broadcast to a topic, the message is only sent to nodes that have at least one process subscribed to that topic</p>
</blockquote>
</aside>
<p>You’re right that this optimization is possible. I don’t know the Phoenix PubSub internals but it makes sense that they would use it.</p>
<p>But I think you’re overestimating how helpful this actually is. Imagine you have 100 nodes and 1000 rooms, where each room has 100 users. Users are load-balanced across nodes, randomly.</p>
<p>Because the assignment of users to nodes is unaware of the assignment of users to <em>rooms</em>, the average number of nodes exchanging messages for each room will be quite large. This is just topologically wrong.</p>
<p>This matters in a high-performance context. Things like voice/video chat, game servers, <em>really</em> complicated multiplayer apps like Figma, etc. Remember, for even moderately complex stuff my answer was “use Phoenix Sync”!</p>
<p>I would be very interested in a counter-example here. An app in a category like those above which fans messages out across nodes in this way. I am unable to come up with anything.</p>
<aside class="quote no-group" data-username="bartblast" data-post="39" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Topics could be hierarchical, pattern-based, or support more sophisticated matching</p>
</blockquote>
</aside>
<p>And in the limit they would use turing-complete code for routing. There is a certain point at which I would argue this just isn’t PubSub anymore. But if you want to call that “thing” PubSub then I am fine with that “thing”!</p>
<aside class="quote no-group" data-username="bartblast" data-post="39" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>As I mentioned earlier in the thread, pub/sub is a messaging primitive</p>
</blockquote>
</aside>
<p>We are a bit in the weeds here but what I am really trying to say is:</p>
<p>PubSub is not a very good messaging primitive. A much better messaging primitive is: <em>messages</em>! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374620" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-374620" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374620"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #39"></div>
  </section>
</div>
    <div class="postbit" id="374621" data-post-id="374621">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="39" data-topic="72519">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Phoenix PubSub provides battle-tested solutions for exactly these challenges.</p>
</blockquote>
</aside>
<p>And BTW this was my <em>other</em> question. Phoenix PubSub <em>does</em> already provide PubSub, so why does Hologram need to re-implement it again?</p>
<p>I think in general an application framework should be focused on providing general solutions so that users can integrate with something <em>like</em> PubSub if they want to. It sounds like you instead want to provide an opinionated PubSub implementation as a core Hologram feature, and that’s what I don’t really like because I don’t think PubSub is all that great!</p>
<p>I think if you <em>do</em> want to provide something opinionated and tightly integrated the IVM stuff as discussed earlier is a better path. But it is of course more work (often true of things which are better).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="374621" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/time-to-implement-pub-sub-in-hologram-looking-for-your-input/72519/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-374621" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="374621"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #40"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/72519/load_more?page=5">Load more posts (8 remaining)</a>
</div></template></turbo-stream>