Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Create Update Feed #117

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open

Conversation

aajjbb
Copy link
Collaborator

@aajjbb aajjbb commented Jul 28, 2017

This PR has the goal of creating a update feed in LuaRocks, basically showing the users whats new from the modules and users they follow.

assert.same 0, #followings
assert.same 0, #events
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails because of the comment mentioned above in flows/followings.moon

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently "only" in tests the event created in follow_object can't be found and isn't deleted.

@@ -41,5 +51,6 @@ class FollowingsFlow extends Flow
"follow",
@current_user

following\delete!
event\delete! if event
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running tests, if this if gets removed, the test fails with a nil. That's because the find of the event object fails. I'm currently investigating it but I have no clue yet.

@aajjbb
Copy link
Collaborator Author

aajjbb commented Aug 5, 2017

There are a few details missing here besides a proper UI for the timeline.

  • create and deliver an event for module upload/update (with proper tests)
  • think of more test strategies for event/timeline_events to have a better coverage

@aajjbb aajjbb requested a review from leafo August 7, 2017 20:38
Copy link
Collaborator

@leafo leafo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good start, here's my feedback from first pass

inner_content: =>
ul ->
for event in *@current_user\timeline!
row_event = Events\find(event.event_id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both of these will cause the n+1 queries issue: http://leafo.net/guides/postgresql-preloading.html#avoiding-n-and-1-queries

the solution in this case is to use the preload function ahead of time, then use the relation getter to get each object. You'll need to add the missing relation on the timeline events.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently preloading it in timeline method instead of in the widget as I guess it's cleaner to only have presentation in a widget.


switch Events\model_for_object_type(row_event.object_object_type)
when Modules
mod = Modules\find row_event.object_object_id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be preloaded

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are broken because the nested preload of object in timeline.event isn't working.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

href: @url_for("module", user: user.slug, module: mod.name)
}, mod\name_for_display!
when Users
usr = Users\find row_event.object_object_id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be preloaded

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

if Events\model_for_object_type(event.object_object_type) == Users
@@create(Users\find(event.object_object_id), event)

@user_timeline: (user) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably want to either paginate this, or limit to something reasonable like 50 for the time being

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm limiting by 50 but I plan to add pagination soon.

@deliver: (user, event) =>
switch event.event_type
when Events.event_types.update
followers = Followings\select "where object_id = ?", event.object_object_id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object_type should be specified when querying by object_id

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

class TimelineEvents extends Model
@primary_key: { "user_id", "event_id" }

@create: (user, event) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to use an opts argument for all model creation, with assertions on required fields. I know there are some models in the codebase that use this style, but I've been updating them as I see them

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -0,0 +1,32 @@
db = require "lapis.db"
import Model from require "lapis.db.model"
import Events, Followings, Users from require "models"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to avoid putting module requires on the top level, and instead in the methods, to prevent any issues with circular dependencies in the future

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

}}
}

@create: (user, object, event_type) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to use an opts argument for all model creation, with assertions on required fields. I know there are some models in the codebase that use this style, but I've been updating them as I see them

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

migrations.moon Outdated
{"event_type", enum}
{"source_user_id", enum}
{"object_object_id", enum}
{"object_object_type", foreign_key}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be enum

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

migrations.moon Outdated
create_table "events", {
{"id", serial}
{"event_type", enum}
{"source_user_id", enum}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two should be foreign_key

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source_user_id really should be a foreign key but event_type too ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure if I understand what columns should be changed. I've changed the way I thought it made sense, could you check the changes out ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -12,7 +12,8 @@ class FollowingsFlow extends Flow
super ...
assert_error @current_user, "must be logged in"

follow_object: (object, type) =>
follow_object: (object, type) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation looks messed up

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@@ -25,6 +26,9 @@ class FollowingsFlow extends Flow
Notifications\notify_for target_user, object,
type, @current_user

event = Events\create(@current_user, object, Events.event_types.subscription)
TimelineEvents\deliver(@current_user, event)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure you're delivering the event to the right person? If I follow someone then I would expect an event to show up on their timeline?

Additionally, we already have notifications for follows, do we want to also have timeline events?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends, maybe not sending the event to the followed timeline is better (and save some processing).

Yeah, for followings, I guess the notifications that are present are enough.

Do you an idea about what kind of stuff show be added to a timeline ?

@@ -35,6 +39,13 @@ class FollowingsFlow extends Flow
type: Followings.types\for_db type
}

event = Events\find {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so when you unfollow something you'd like all the events cleaned from your timeline (eg. they pushed 10 new updates to their module) Given that, you'll need to use select to handle something like that, since find only returns one row. Also, you don't want to delete the event, but you want to delete the timeline_event

the logic to do this is semi-complicated, so maybe it could be a method on a model, or in a timeline flow

@@ -6,13 +6,13 @@ import request_as from require "spec.helpers"
factory = require "spec.factory"


import Modules, Versions, Followings, Users, Notifications, NotificationObjects from require "models"
import Modules, Versions, Events, Followings, Users, Notifications, NotificationObjects from require "spec.models"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spec.models adds a before_each to truncate, so you should move this entire line into the describe, and then you can remove the redundant trucate_tables method call in the existing before_each

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Modules
Users from require "spec.models"

import Events, TimelineEvents from require "models"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convert this to require from spec.models and put it inside the describe block

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

object: module
event_type: Events.event_types.subscription
}
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird formatting

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

…this fixed the broken preloads in timeline_events widget too
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants