Skip to content

Commit d20bc61

Browse files
committed
auto-restart after 2G memory, add flash middleware, refactor newsletters (multiple per subscription)
1 parent a842672 commit d20bc61

22 files changed

Lines changed: 336 additions & 153 deletions

File tree

ecosystem.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
{
22
"apps": [
33
{
4-
"name": "Javascript.ru",
5-
"script": "bin/server",
6-
"instances": "1",
7-
"exec_mode": "cluster_mode",
8-
"env": {
4+
"name": "Javascript.ru",
5+
"script": "bin/server",
6+
"instances": "1",
7+
"exec_mode": "cluster_mode",
8+
"max_memory_restart": "2G",
9+
"env": {
910
"HOST": "127.0.0.1",
1011
"PORT": "3000",
1112
"PM2_GRACEFUL_LISTEN_TIMEOUT": 1000,
1213
"PM2_GRACEFUL_TIMEOUT": 5000
1314
},
14-
"env_production": {
15-
"NODE_ENV": "production",
16-
"SITE_HOST": "https://learn.javascript.ru",
17-
"STATIC_HOST": "https://js.cx",
18-
"ASSET_VERSIONING": "file"
15+
"env_production": {
16+
"NODE_ENV": "production",
17+
"SITE_HOST": "https://learn.javascript.ru",
18+
"STATIC_HOST": "https://js.cx",
19+
"ASSET_VERSIONING": "file"
1920
}
2021
}
2122
],
2223
"deploy": {
23-
"nightly": {
24+
"nightly": {
2425
"user": "root",
2526
"host": "nightly",
2627
"pre-deploy": "cd /root/javascript-nodejs; bash ./pm2/pre_deploy.sh",
@@ -30,7 +31,7 @@
3031
"test": "echo 'no test on deploy right now'",
3132
"post-deploy": "NODE_LANG=ru bash ./pm2/post_deploy.sh"
3233
},
33-
"yuri": {
34+
"yuri": {
3435
"user": "root",
3536
"host": "yuri",
3637
"pre-deploy": "cd /root/javascript-nodejs; bash ./pm2/pre_deploy.sh",

fixture/init.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,24 @@ exports.OrderTemplate = [
4747

4848
exports.Newsletter = [
4949
{
50-
title: "Курс Node.JS",
51-
slug: "nodejs"
50+
title: "Курс и скринкасты по Node.JS / IO.JS",
51+
slug: "nodejs",
52+
period: "бывают редко",
53+
weight: 1,
54+
internal: false
5255
},
5356
{
54-
title: "Курс JavaScript / DOM / Интерфейсы",
57+
title: "Курс JavaScript/DOM/интерфейсы",
58+
period: "раз в 1.5-2 месяца",
59+
weight: 0,
60+
internal: false,
5561
slug: "js"
5662
},
5763
{
58-
title: "Продвинутые курсы, мастер-классы и конференции по JavaScript",
64+
title: "Другие продвинутые скринкасты, курсы, конференции и мастер-классы по JavaScript",
65+
period: "редко",
66+
weight: 2,
67+
internal: false,
5968
slug: "advanced"
6069
}
6170
];

handlers/flash/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
exports.init = function(app) {
3+
// koa-flash is broken
4+
// reading from one object, writing to another object
5+
// occasionally writing to default
6+
app.use(function *flash(next) {
7+
this.flash = this.session.flash || {};
8+
9+
this.session.flash = {};
10+
11+
Object.defineProperty(this, 'newFlash', {
12+
get: function() {
13+
return this.session.flash;
14+
},
15+
set: function(val) {
16+
this.session.flash = val;
17+
}
18+
});
19+
20+
yield *next;
21+
22+
if (Object.keys(this.session.flash).length === 0) {
23+
// don't write empty flash
24+
delete this.session.flash;
25+
}
26+
27+
if (this.status == 302 && this.session && !this.session.flash) {
28+
// pass on the flash over a redirect
29+
this.session.flash = this.flash;
30+
}
31+
});
32+
33+
app.use(function*(next) {
34+
35+
var notificationTypes = ["error", "warning", "info", "success"];
36+
37+
// by default koa-flash uses same defaultValue object for all flashes,
38+
// this.flash.message writes to defaultValue!
39+
40+
this.addFlashMessage = function(type, html) {
41+
// split this.flash from defaultValue (fix bug in koa-flash!)
42+
if (!this.newFlash.messages) {
43+
this.newFlash.messages = [];
44+
}
45+
46+
if (!~notificationTypes.indexOf(type)) {
47+
throw new Error("Unknown flash type: " + type);
48+
}
49+
50+
this.newFlash.messages.push({
51+
type: type,
52+
html: html
53+
});
54+
};
55+
56+
yield* next;
57+
58+
});
59+
};

handlers/jb/router.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ router.get('/go', function*() {
1616
cookie: this.get('cookie')
1717
});
1818

19-
2019
this.status = 301;
2120
this.redirect('https://www.jetbrains.com/webstorm/?utm_source=javascript.ru&utm_medium=banner2&utm_campaign=webstorm');
2221
});

handlers/newsletter/controllers/confirm.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
const path = require('path');
21
const Newsletter = require('../models/newsletter');
32
const Subscription = require('../models/subscription');
4-
const sendMail = require('mailer').send;
53
const config = require('config');
64

75
exports.get = function*() {
86
this.nocache();
7+
98
const subscription = yield Subscription.findOne({
109
accessKey: this.params.accessKey
1110
}).exec();
@@ -17,6 +16,7 @@ exports.get = function*() {
1716
subscription.confirmed = true;
1817
yield subscription.persist();
1918

20-
this.body = this.render('confirm');
19+
this.addFlashMessage('success', 'Подписка подтверждена.');
20+
this.redirect('/newsletter/subscriptions/' + this.params.accessKey);
2121

2222
};

handlers/newsletter/controllers/remove.js

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const path = require('path');
2+
const Newsletter = require('../models/newsletter');
3+
const Subscription = require('../models/subscription');
4+
const sendMail = require('mailer').send;
5+
const config = require('config');
6+
7+
// subscribe a single newsletter (post from somewhere outside of the module)
8+
exports.post = function*() {
9+
10+
const newsletter = yield Newsletter.findOne({
11+
slug: this.request.body.slug
12+
}).exec();
13+
14+
if (!newsletter) {
15+
this.throw(404, "Нет такой рассылки");
16+
}
17+
18+
if (this.req.user && this.req.user.email == this.request.body.email) {
19+
// registered users need no confirmation
20+
21+
var subscription = yield Subscription.findOne({
22+
email: this.request.body.email
23+
}).exec();
24+
25+
if (subscription) {
26+
subscription.newsletters.addToSet(newsletter._id);
27+
subscription.confirmed = true;
28+
} else {
29+
subscription = new Subscription({
30+
email: this.request.body.email,
31+
newsletters: [newsletter._id],
32+
confirmed: true
33+
});
34+
}
35+
36+
yield subscription.persist();
37+
38+
this.body = {
39+
message: `Вы успешно подписаны, ждите писем на адрес ${subscription.email}.`
40+
};
41+
42+
} else {
43+
var subscription = yield Subscription.findOne({
44+
email: this.request.body.email
45+
}).exec();
46+
47+
if (!subscription) {
48+
subscription = new Subscription({
49+
email: this.request.body.email,
50+
confirmed: false
51+
});
52+
}
53+
54+
subscription.newsletters.addToSet(newsletter._id);
55+
56+
yield subscription.persist();
57+
58+
if (subscription.confirmed) {
59+
this.body = {
60+
message: `Вы успешно подписаны.`
61+
};
62+
} else {
63+
64+
yield sendMail({
65+
templatePath: path.join(this.templateDir, 'confirm-email'),
66+
subject: "Подтверждение подписки на JavaScript.ru",
67+
to: subscription.email,
68+
link: (config.server.siteHost || 'http://javascript.in') + '/newsletter/confirm/' + subscription.accessKey
69+
});
70+
71+
this.body = {
72+
message: `Проверьте почту ${subscription.email} и подтвердите подписку, перейдя по ссылке в письме.`
73+
};
74+
}
75+
}
76+
77+
78+
};
79+

0 commit comments

Comments
 (0)