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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jaybe78" data-post="1" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>Obviously the complexity here is that I have to fetch a lot of data at the same time, it represents a lot of queries, so I thought about using genstage or broadway…</p>
</blockquote>
</aside>
<p>you are going to be writing and reading from the DB probably way above what it can handle. but if you put something like memcached infront of your server that can easily handle 200k reads a second, or more if it’s on the app server. if you are careful with how you use memcached then you can probably avoid most DB queries for a scenario where someone signs up and logs in. if ETS is shared among all your servers then it should be a similar benefit, however you’ll have to add your own cleanup code i presume.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356203" 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/fetch-online-userss-friends-for-large-quantity-of-users/69343/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-356203" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356203"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="356209" data-post-id="356209">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jaybe78" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/120/36069_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jaybe78
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>i am unsure of the scope of the problem. do you have data and usage patterns, expected active users per second?</p>
</blockquote>
<p>The idea is for any users to see his list of friends “active”.<br>
In my app an active player is not just a player online but a player available to play.</p>
<p>So basically the query I run fetch data with status != “away” and “busy” and “offline”<br>
An user can go from “available” to “busy” really quickly, meaning he just found a player to play with.</p>
<p>Then, he’d stay “busy” for a little while, 1 hour or less before going back to “available”.<br>
Multiple 10s of thousands of users can request their friends at the same time.</p>
<blockquote>
<p>for example you can have a table that records the last time someone logged on/off the site</p>
</blockquote>
<p>As described in my  previous answer, I would use the <code>Users</code> table and batch update the “last_active_date” and “status” in order to do so.</p>
<blockquote>
<p>how often is someone going to need to know about the 1000 friends statuses?</p>
</blockquote>
<p>Among 1000 friends, first, I guess only a portion of them will be returned by the query with the  status “available” from the DB.</p>
<p>So, let’s say I get 200 returned, the idea is to use a combination of PubSub and Phoenix Presence to track them afterwards.</p>
<p>My app is a mobile app, and since I only display something like 20/30 users on the screen at one time, I will have a pool of 200 users, but only subscribe a user to those on demand.</p>
<p>For example, when the user scrolls to see the next 30, I can unsubscribe from the ones that are not visible anymore on the screen, and subscribe to the new ones.</p>
<blockquote>
<p>for example you can have a table that records the last time someone logged on/off the site</p>
</blockquote>
<p>Yes except if I misunderstand, that’s more or less what I explained there <a href="https://forum.elixirforum.com/t/fetch-online-userss-friends-for-large-quantity-of-users/69343/18" class="inline-onebox" rel="nofollow">Fetch online users's friends for large quantity of users - #18 by jaybe78</a></p>
<blockquote>
<p>even if you aren’t doing predictions you only need active users in your graph + friend nodes, unless i misunderstand the problem.</p>
</blockquote>
<p>That’s exactly what I want.</p>
<p>Except if I’m missing something I see that in 2 steps:</p>
<ol>
<li>
<p>First step is to fetch a user friends that are most probably online and available<br>
That is done in the SQL DB using “status”/ “last_active” columns joined with Friends table</p>
</li>
<li>
<p>The second step is that I want user to see in real time when one of their friend goes from “available” to “unavailable”, and that’s why at this point, I want to use Phoenix Presence on a subset of all the friends returned from the query</p>
</li>
</ol>
<blockquote>
<p>you are going to be writing and reading from the DB probably way above what it can handle.</p>
</blockquote>
<p>Well I understand that and that’s why I want to use something like broadway to get some back pressure on the SQL DB .</p>
<p>Are you saying that is not necessary if the work done in ETS table or memcach is good enough ?</p>
<blockquote>
<p>if ETS is shared among all your servers then it should be a similar benefit<br>
Well my idea was actually not to necessarily to duplicate the stored data in ETS across all nodes but do some rpc call/async_call to search for some friends on other nodes.<br>
It would be a lot of broadcast around to publish the new relationships across all nodes and that would create duplicate data on all tables.</p>
</blockquote>
<p>So the flow would be</p>
<ol>
<li>A user joins the friends screen</li>
<li>We search for some relation in local ets tables and across the cluster</li>
<li>if nothing is found or all users are busy we can query the DB to get new friends</li>
<li>When we get some friends potentially available, we subscribe to them, not more than 40/50 at a time and return that to the UI</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356209" 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/fetch-online-userss-friends-for-large-quantity-of-users/69343/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-356209" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356209"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="356258" data-post-id="356258">
  <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="jaybe78" data-post="18" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>I don’t want a user to scroll through a hundreds of his friends in search of someone online to play with.<br>
That would be a waste of time… especially for someone with 1000 or more friends whose only friend online is at the very bottom of the list</p>
</blockquote>
</aside>
<p>Well yeah, you would sort the friends online-first in the UI. This is what literally every friends list UI I’ve ever seen does.</p>
<aside class="quote no-group" data-username="jaybe78" data-post="18" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>Regarding scanning table, it’s really not an option for me, would be a waste of time, performance</p>
</blockquote>
</aside>
<p>“Scanning” in my reply was a technical term referring to how the database executes your query. <em>You</em> would be writing a query, the <em>database</em> is scanning. You would of course want an index on the thing you’re scanning, which in this case would be the <code>friends</code> relation. You would want an index on <code>(user_id, friend_id)</code> to make that fast. I would just use that tuple as the primary key and kill two birds with one stone.</p>
<p>Obviously you would want that to be bidirectional so I guess you would either create two <code>friends</code> entries (one each way) for every pair of friends <em>or</em> create a second index and scan both. I’m not sure if there is a better way to model that.</p>
<aside class="quote no-group" data-username="jaybe78" data-post="18" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>I heard Materialized views do not scale very well, and about partitioning the Friends table ? would that really benefit in anything</p>
</blockquote>
</aside>
<p>Materialized views are not updated incrementally in Postgres IIRC but all at once, so obviously that creates performance problems. I can’t speak to partitioned tables, maybe someone else has experience with that.</p>
<aside class="quote no-group" data-username="jaybe78" data-post="18" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>At the app level to improve even more performance, once the first users joining start fetching their friends I can store in memory their relationship for each of them</p>
</blockquote>
</aside>
<p>What you are describing here is just caching, right? Sounds good to me.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356258" 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/fetch-online-userss-friends-for-large-quantity-of-users/69343/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-356258" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356258"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="356259" data-post-id="356259">
  <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="jaybe78" data-post="23" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>Among 1000 friends, first, I guess only a portion of them will be returned by the query with the status “available” from the DB.</p>
<p>So, let’s say I get 200 returned, the idea is to use a combination of PubSub and Phoenix Presence to track them afterwards.</p>
</blockquote>
</aside>
<p>Careful: if you retrieve and track only the <em>online</em> friends then users who come online <em>after</em> you look up the friends will never appear.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356259" 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/fetch-online-userss-friends-for-large-quantity-of-users/69343/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-356259" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356259"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="356292" data-post-id="356292">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jaybe78" data-post="23" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>As described in my previous answer, I would use the <code>Users</code> table and batch update the “last_active_date” and “status” in order to do so.</p>
</blockquote>
</aside>
<p>you could put this data in a different table that is partitioned on date. having a buffer that you then write out periodically should work. i think you should avoid that in the beginning.</p>
<p>i’m starting to see why you want to use something like dynamoDB, however postgres can handle 30k writes/s, though you may have to do some tuning. i think this is something you would have to test with any DB you use.</p>
<p>in postgres you can also make unlogged tables. if you are trying to get high writes and don’t care much about data loss in crashes.</p>
<p>if you think that you are going to be doing a heavy write load that is going to go beyond the limits of something like postgres or event the postgres providers (planetscale, aurora), then you could try something like rocksdb, which can handle 100k-200k writes. something that uses a LSM (log structured merge) should be fast. maybe you could do rocks for some data, or all the data, 1 DB is simpler than many.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356292" 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/fetch-online-userss-friends-for-large-quantity-of-users/69343/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-356292" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356292"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="356293" data-post-id="356293">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jaybe78" data-post="23" data-topic="69343">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jaybe78/48/36069_2.png" class="avatar"> jaybe78:</div>
<blockquote>
<p>My app is a mobile app, and since I only display something like 20/30 users on the screen at one time, I will have a pool of 200 users, but only subscribe a user to those on demand.</p>
<p>For example, when the user scrolls to see the next 30, I can unsubscribe from the ones that are not visible anymore on the screen, and subscribe to the new ones.</p>
</blockquote>
</aside>
<p>I think it is worth it to try a simpler solution first. have a subscription for all of a users friends instead of a sub for each online friend. on the server you may want to use 2 lists per user for figuring out dispatch/rendering. a list of their friends, and a list of observers. maybe these 2 lists sound redundant, but you’ll be able to add a backoffice or followers without doing hacky stuff to the render list. when something changes with a user you iterate through the observers and dispatch status. if you get to the point where this kills your server then you can use something like a message queue for update dispatching, or use delays.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="356293" data-batch-url="/posts/batch_likers">
                        2
                      </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/fetch-online-userss-friends-for-large-quantity-of-users/69343/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-356293" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="356293"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>