9 ms·
An HN style social news site written in Ruby/Sinatra/Redis/JQuery by Antirez
- upgrayedd 15y agoJoin us in #lamernews on freenode, also if antirez reads this you're welcome to ops.
- coderdude 15y agoI don't know if the creator is going to see these comments but lamernews.com goes to a GoDaddy parked domain page. Not sure if DNS changes just need to propagate or what.
- jonpaul 15y agoI agree completely... I was hoping to see a live version. Live versions can help OSS spread and generate hacker interest. However, it should be noted that I'm thankful that the author decided to share this.
- antirez 15y agoHi Jon! here it is almost the contrary, I wrote the code especially to run it as a real service. It is just that it needs a few more days. But actually... I can just run it easily in a server of mine just to show it to you. Let's try to install it... just a moment.
- oppegard 15y agoHere it is running on Cloud Foundry: http://lamernews.cloudfoundry.com http://lamernews.cloudfoundry.com
- antirez 15y agoHi, this is just the first public release. Hope to get more features inside and more testing before actually installing the first version into lamernews.com. The code base got just a few days of after-work hacking, so probably this will take a few more days to be ready. Thanks for the hint.
- daeken 15y agoJust noticed you're using a single pass of SHA1 (salted) for password storage. Would you be opposed to a patch using a safer password storage mechanism? If not, I'll throw one your way in a couple hours.
- antirez 15y agoif what you are thinking about is to use blowfish or other algorithm with a slow key scheduling step, what about if we just reiterate N times SHA1? Should be exactly as secure, like in: SHA1(SHA1(SHA1(0|pass)|1)|2) and so forth. This way there is no requirement for an additional library.
- daeken 15y agoI would strongly recommend that rather than doing that, go with standard PBKDF2. In essence, HMAC(HMAC(HMAC(...(password)))) with a per-user salt. I generally recommend 10k+ rounds with PBKDF2 (each one is cheap). This wouldn't give you an additional dependency and is super easy to put in place -- I'll do it, if you want.
- codahale 15y agohttps://github.com/emerose/pbkdf2-ruby https://github.com/emerose/pbkdf2-ruby
- pjscott 15y agoIf you concatenate your password and a salt, then iterate a cryptographic hash like SHA256 a few thousand times, this is almost exactly PBKDF1. It's a good, respectable password hashing scheme. The main advantage that PBKDF2 offers is the ability to produce arbitrary output sizes. (The difference between this and PBKDF1 is that PBKDF1 requires using either MD2 or SHA1 as the hash function, and hasn't been updated to reflect the availability of SHA-256 and SHA-512.)
- typicalrunt 15y agoGreat stuff, thanks antirez. I like it when creators of libraries build a complex system to eat their own dog food. It helps me visualize use cases other than simple 15-minute blog projects.
- antirez 15y agoThanks this was one of the main goals, to have a non trivial example, and even to put it into production. It is very helpful for me to vest the clothes of the user, it makes me understanding a lot more about Redis. If you are always in the other side of the table you miss a lot.
- Derferman 15y ago> Don't use templates, they suck. This is surprising. Why not make minimal use of ERB or Mustache?
- erikpukinskis 15y agoIt seems like they just reimplemented a custom HAML subset.
- riffraff 15y agolooks more like CGI::HtmlExtension in the ruby's stdlib but with hash as params
- alnayyir 15y agoThis is awesome, thanks! I wanted an alternative to HN anyway. :)
- nathanwdavis 15y agoWhat I like most about this is that it is a non-trivial, non-toy example of using Redis effectively. Thanks antirez!!
- julian37 15y agoPerfect timing as I'm planning to use Redis for the first time soon and this is going to be a great resource for best practices. Thanks, Antirez! Speaking of best practices, putting serialized objects into the database (as you're doing with the comment objects) is usually considered an anti-pattern in the SQL world. Could you briefly explain (beyond what you said in the Readme) why you've used this approach for comments, but not for, say, news objects? Was this decision solely made to work around anticipated performance/memory bottlenecks and if so, what are the trade-offs, and are there any rules of thumb for making the same decision for object types in other applications?
- antirez 15y agoHello julian, the difference between comments and news is that a thread (a collection of comments for a given news) is an hash made of sub-hashes, the hash is ID -> comment_hash. The comment hash just contains the different fields. When there are this two levels, storing the first level as a Redis hash, and the second as JSON leads to very good memory usage performances, it is internally stored as a linear array. We can do that because we know most news will have just a few tens of comments. If there are more, the hash will turn into a real hash table transparently, more space, but worth it for the rare cases when this is needed. The news instead is just a collection of fields. There is no outer object that is reasonably sized, like "all the news obeject" (it is too big), so there is no gain in using this approach. What is good about storing sub-objects of hashes as JSON objects is that Redis unstable just got JSON support in Lua scripts, so it will also be able to manipulate this objects sending Redis small Lua scripts. I hope this clarifies the issue.
- julian37 15y agoHi Salvatore, many thanks for the reply, that does clarify the issue. So when sub-objects are only a few dozen per collection (per parent object) on average, storing them as JSON blobs allows Redis to "inline" them, yielding good memory usage. But for large numbers of items per parent, Redis can't inline them so you might as well represent them as a hash, which can never be inlined. Is this a fair summary? I guess that ideally, all objects would always be represented in the same way from a client perspective, and the database engine would decide which internal format is best suited for storage, maybe using hints provided by the client, and handle any necessary (de)serialization as an implementation detail. That said, I know Redis is still a young project and I suppose this is something you guys are thinking to improve long-term anyway. Cheers!
- kennystone 15y agoRedis seems like a poor choice if you want the comments and stories to stick around for a while. It's designed to be an in-memory database...
- antirez 15y agoRedis is perfectly fine for this application, both from the point of view of data persistence since AOF is very durable, and from the point of view of space needed. This application is designed to hold a lot of news and comments even using little memory.
- cnu 15y ago> This application is designed to hold a lot of news and comments even using little memory. Can you post some benchmarks on that? Would like to see how many (average sized) news/comments can be stored on the 512mb VPS.
- tomatohs 15y agoConsidering the creator of lamernews is also one of the creators of redis, he probably knows what hes doing.
- revorad 15y agoAs I've already mentioned to antirez, the only suitable mascot is this - http://www.google.com/search?q=llama&hl=en&tbm=isch&biw=1069&bih=593 http://www.google.com/search?q=llama&hl=en&tbm=isch&...
- ohyes 15y agoWhat do you do when you get more data than fits into ram? I've been working on a 'for fun' application with Redis, and had been counting on some sort of on disk memory. (Because storing everything in ram is comparatively expensive, I had figured I could use Diskstore or VM with a small server to start). Now I'm considering porting over to a mongodb or sql backend because the disk based storage options won't be supported in Redis in the future. What should I do? Simply Use Redis as a cache? Buy RAM? Doesn't that seem to limit its utility and complicate things?
- LeafStorm 15y agoThe two attempts at disk storage so far - VM and Diskstore - are both based on the concept of RAM as the primary datastore and the disk as merely auxiliary storage. However, antirez is a perfectionist, so he scrapped both of them when they didn't work as well as he had hoped. In the long term (i.e. after cluster is finished), there are plans to manipulate data structures directly on disk (an incredibly elegant solution, and also really good for SSDs). Though in the short term, you are right in that RAM is far more expensive than disk, and this does limit the utility of Redis as a primary datastore.
- llimllib 15y agoSo... what's going to happen when lamernews runs out of RAM?
- nknight 15y agoThat's pretty mind-numbingly self-evident, isn't it? The kernel kills Redis and the site is down.
- aaronblohowiak 15y agodepending on your settings. the kernel could also page out some RAM, which early reports suggest isnt so bad on a high-end ssd.
- 15y ago
- AndrewVos 15y agoYour site lamernews.com is showing godaddy adverts.
- compay 15y agoIt would be great if somebody added some tests.
- xetorthio 15y agoyeah... I wonder where are all the tests :)
- EricR23 15y agoThis is really cool! I just setup my own deployment of this at rubynews.heroku.com :) I've fixed some styling issues and I'm thinking of tweaking a few things... I may contribute to this on github. Thanks!
- typicalrunt 15y agoHi Antirez, Looking at the source, you use side-effects to return user objects and such. I've always been taught side-effects are a bad thing that create complex code, which seems to go against one of the goals listed in your README.md. # Try to authenticate the user, if the credentials are ok we populate the # $user global with the user information. # Otherwise $user is set to nil, so you can test for authenticated user # just with: if $user ... # # Return value: none, the function works by side effect. def auth_user(auth) return if !auth id = $r.get("auth:#{auth}") return if !id user = $r.hgetall("user:#{id}") $user = user if user.length > 0 end Can you explain why you used side-effects?
- deleted 15y ago[deleted]
- supersillyus 15y agoThis should be the new "Hello world" for web-oriented languages and frameworks. I'd love to see this ported idiomatically to different languages.