Skip to content

Commit bda9911

Browse files
authored
Merge pull request #3286 from artsy/staging
Deploy
2 parents 275ec1c + a098d0d commit bda9911

File tree

3 files changed

+211
-1
lines changed

3 files changed

+211
-1
lines changed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
require('node-env-file')(require('path').resolve __dirname, '../.env')
2+
{ MongoClient } = require 'mongodb'
3+
path = require 'path'
4+
{ indexForSearch } = require '../src/api/apps/articles/model/distribute'
5+
Article = require '../src/api/apps/articles/model/index.js'
6+
search = require '../src/api/lib/search_client'
7+
asyncLib = require 'async'
8+
9+
env = require 'node-env-file'
10+
switch process.env.NODE_ENV
11+
when 'test' then env path.resolve __dirname, '../.env.test'
12+
when 'production', 'staging' then ''
13+
else env path.resolve __dirname, '../.env'
14+
15+
# Check for dry-run flag
16+
isDryRun = process.argv.includes('--dry-run')
17+
18+
console.log('=' .repeat(80))
19+
console.log('REINDEXING VIDEO ARTICLES')
20+
if isDryRun
21+
console.log('🔍 DRY RUN MODE - No changes will be made')
22+
console.log('=' .repeat(80))
23+
console.log('Environment:', process.env.NODE_ENV || 'development')
24+
console.log('MongoDB URL:', process.env.MONGOHQ_URL ? 'Configured' : 'NOT CONFIGURED')
25+
console.log('Search Configuration:')
26+
console.log(' - URL:', process.env.SEARCH_URL || 'NOT CONFIGURED')
27+
console.log(' - Index Name:', search.index)
28+
console.log(' - Index Suffix:', process.env.SEARCH_INDEX_SUFFIX || 'production')
29+
if isDryRun
30+
console.log('Mode: DRY RUN (use without --dry-run flag to perform actual reindexing)')
31+
console.log('=' .repeat(80))
32+
console.log()
33+
34+
main = ->
35+
startTime = Date.now()
36+
console.log('Connecting to MongoDB...')
37+
38+
client = new MongoClient(process.env.MONGOHQ_URL)
39+
client.connect()
40+
.then (client) ->
41+
console.log('✓ Connected to MongoDB successfully')
42+
db = client.db()
43+
console.log('✓ Database connection established')
44+
return db.collection('articles')
45+
.then (articlesCollection) ->
46+
console.log('✓ Articles collection accessed')
47+
console.log('Fetching video articles (published: true, layout: video)...')
48+
49+
# Find only published video articles
50+
articlesCollection.find({
51+
layout: 'video'
52+
published: true
53+
}).sort({ published_at: -1 }).toArray()
54+
.then (articles) ->
55+
console.log('✓ Found ' + articles.length + ' video articles to reindex')
56+
console.log()
57+
58+
if articles.length is 0
59+
console.log('No video articles found. Exiting.')
60+
return client.close().then -> process.exit(0)
61+
62+
# Show sample of articles to be reindexed
63+
console.log('Articles to be reindexed:')
64+
for article in articles
65+
hasMedia = article.media?.url?
66+
status = if hasMedia then '' else '✗ NO MEDIA URL'
67+
console.log(" #{status} #{article.title} (#{article._id})")
68+
console.log()
69+
70+
if isDryRun
71+
console.log('🔍 DRY RUN MODE: Skipping actual indexing')
72+
console.log('✅ Connection successful!')
73+
console.log('✅ Found ' + articles.length + ' video articles that would be reindexed')
74+
console.log()
75+
console.log('To perform actual reindexing, run without the --dry-run flag')
76+
return client.close().then -> process.exit(0)
77+
78+
console.log('Starting indexing process...')
79+
console.log()
80+
81+
new Promise (resolve, reject) ->
82+
processedCount = 0
83+
errorCount = 0
84+
successCount = 0
85+
86+
asyncLib.mapSeries articles, (article, cb) ->
87+
processedCount++
88+
console.log("=" .repeat(80))
89+
console.log("[#{processedCount}/#{articles.length}] Processing: #{article.title}")
90+
console.log(" Article ID: #{article._id}")
91+
console.log(" Layout: #{article.layout}")
92+
console.log(" Published: #{article.published}")
93+
console.log(" Has media.url: #{!!article.media?.url}")
94+
95+
indexWorker article, (err) ->
96+
if err
97+
errorCount++
98+
console.error(" ✗ ERROR indexing article: #{err.message}")
99+
else
100+
successCount++
101+
console.log(" ✓ Successfully indexed")
102+
console.log()
103+
cb(null) # Continue even if there's an error
104+
, (err, results) ->
105+
resolve({ results, errorCount, successCount, processedCount })
106+
.then ({ results, errorCount, successCount, processedCount }) ->
107+
endTime = Date.now()
108+
duration = Math.round((endTime - startTime) / 1000)
109+
110+
console.log('=' .repeat(80))
111+
console.log('REINDEXING COMPLETE')
112+
console.log('=' .repeat(80))
113+
console.log('📊 Summary:')
114+
console.log(" - Total processed: #{processedCount}")
115+
console.log(" - Successfully indexed: #{successCount}")
116+
console.log(" - Errors: #{errorCount}")
117+
console.log(" - Duration: #{duration} seconds")
118+
console.log('=' .repeat(80))
119+
console.log()
120+
console.log('Closing database connection...')
121+
122+
client.close()
123+
.then ->
124+
console.log('✓ Database connection closed successfully')
125+
console.log()
126+
console.log('✅ Script completed!')
127+
if errorCount > 0
128+
console.log('⚠️ Some errors occurred. Check logs above.')
129+
process.exit(1)
130+
else
131+
process.exit(0)
132+
.catch (err) ->
133+
console.error('✗ Error closing database connection:', err)
134+
process.exit(1)
135+
.catch (err) ->
136+
console.error('=' .repeat(80))
137+
console.error('✗ FATAL ERROR')
138+
console.error('=' .repeat(80))
139+
console.error('Error:', err.message)
140+
console.error('Stack:', err.stack)
141+
console.error('=' .repeat(80))
142+
143+
client.close()
144+
.then -> process.exit(1)
145+
.catch -> process.exit(1)
146+
147+
indexWorker = (article, cb) ->
148+
try
149+
articlePresent = Article.present(article)
150+
151+
indexForSearch articlePresent, (err) ->
152+
if err
153+
cb(err)
154+
else
155+
cb()
156+
catch err
157+
cb(err)
158+
159+
console.log('Initializing video article reindexing...')
160+
if isDryRun
161+
console.log('Running in DRY RUN mode - no changes will be made')
162+
console.log()
163+
main()

src/api/models/article.coffee

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ module.exports = class Article extends Backbone.Model
4343
@get('channel_id')?.toString() is EDITORIAL_CHANNEL
4444

4545
isVisibleToPublic: ->
46-
@get('published') && @isEditorial() && @get('sections')?.length > 0
46+
hasContent = @get('sections')?.length > 0 || !!@get('media')?.url
47+
@get('published') && @isEditorial() && hasContent
4748

4849
replaceTagWith: (htmlStr, findTag, replaceTag) ->
4950
$ = cheerio.load(htmlStr)

src/api/test/models/article.test.coffee

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,49 @@ describe "Article", ->
118118
'artsy-editorial-test3'
119119
]
120120
@article.slug().should.equal 'artsy-editorial-test3'
121+
122+
describe '#isVisibleToPublic', ->
123+
124+
it 'returns true for published editorial articles with sections', ->
125+
@article.set
126+
published: true
127+
channel_id: '12345'
128+
sections: [{ type: 'text', body: 'test content' }]
129+
@article.isVisibleToPublic().should.be.true()
130+
131+
it 'returns true for published editorial video articles with media', ->
132+
@article.set
133+
published: true
134+
channel_id: '12345'
135+
sections: []
136+
media: { url: 'https://example.com/video.mp4' }
137+
@article.isVisibleToPublic().should.be.true()
138+
139+
it 'returns false for unpublished articles', ->
140+
@article.set
141+
published: false
142+
channel_id: '12345'
143+
sections: [{ type: 'text', body: 'test content' }]
144+
@article.isVisibleToPublic().should.be.false()
145+
146+
it 'returns false for non-editorial articles', ->
147+
@article.set
148+
published: true
149+
partner_channel_id: '67890'
150+
sections: [{ type: 'text', body: 'test content' }]
151+
@article.isVisibleToPublic().should.be.false()
152+
153+
it 'returns false for articles with no content', ->
154+
@article.set
155+
published: true
156+
channel_id: '12345'
157+
sections: []
158+
@article.isVisibleToPublic().should.be.false()
159+
160+
it 'returns false for video articles without media url', ->
161+
@article.set
162+
published: true
163+
channel_id: '12345'
164+
sections: []
165+
media: {}
166+
@article.isVisibleToPublic().should.be.false()

0 commit comments

Comments
 (0)