Skip to content

Commit a04c8a8

Browse files
committed
Merge pull request #766 from LearningLocker/issue/storedDate
Issue/stored date - requires migration
2 parents 811ed1b + 012e584 commit a04c8a8

File tree

12 files changed

+178
-20
lines changed

12 files changed

+178
-20
lines changed

app/commands/ConvertTimestamp.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ public function fire()
4343
{
4444
Statement::chunk(1000, function($statements){
4545
foreach ($statements as $s){
46-
$s->timestamp = new \MongoDate(strtotime($s->statement['timestamp']));
46+
$timestamp = new Carbon\Carbon($s->statement['timestamp']);
47+
$s->timestamp = new \MongoDate($timestamp->timestamp, $timestamp->micro);
4748
$s->save();
4849
}
4950
$this->info(count($statements) . ' converted.');

app/config/database.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
'default' => 'mongodb',
66
'connections' => [
77
'mongodb' => [
8-
'driver' => 'mongodb',
9-
'host' => 'localhost',
10-
'port' => 27017,
11-
'username' => '',
12-
'password' => '',
13-
'database' => 'll_staging' // Default name (removing this makes Travis fail).
14-
],
8+
'driver' => 'mongodb',
9+
'host' => 'localhost',
10+
'port' => 27017,
11+
'username' => '',
12+
'password' => '',
13+
'database' => 'll_staging' // Default name (removing this makes Travis fail).
14+
],
1515
],
1616
'migrations' => 'migrations',
1717
];

app/controllers/LrsController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public function statements($lrs_id){
198198
'scopes' => ['all']
199199
]),
200200
'scopes' => ['all']
201-
]))->orderBy('statement.stored', 'DESC')->paginate(15);
201+
]))->orderBy('stored', 'DESC')->paginate(15);
202202
return View::make('partials.statements.list', array_merge($this->getLrs($lrs_id), [
203203
'statements' => $statements,
204204
'statement_nav' => true,

app/controllers/api/Exports.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public function __construct(Export $export) {
2323
* @return StreamedResponse.
2424
*/
2525
public function showJson($id) {
26+
// should top timeouts on long queries
27+
set_time_limit(0);
28+
2629
$opts = $this->getOptions();
2730
$model = $this->repo->show($id, $opts);
2831

@@ -46,6 +49,9 @@ public function showJson($id) {
4649
* @return StreamedResponse.
4750
*/
4851
public function showCsv($id) {
52+
// should top timeouts on long queries
53+
set_time_limit(0);
54+
4955
$opts = $this->getOptions();
5056
$model = $this->repo->show($id, $opts);
5157

@@ -92,4 +98,4 @@ private function quoteCSV($field) {
9298
return $field;
9399
}
94100
}
95-
}
101+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Database\Migrations\Migration;
5+
6+
class AddStoredToStatementRoot extends Migration {
7+
8+
/**
9+
* Run the migrations.
10+
*
11+
* @return void
12+
*/
13+
public function up()
14+
{
15+
set_time_limit(0);
16+
17+
$db = \DB::getMongoDB();
18+
$statementsCollection = new MongoCollection($db, 'statements');
19+
20+
$statementsCollection->createIndex(['stored' => 1], ['background'=>1, 'socketTimeoutMS'=>-1]);
21+
$statementsCollection->createIndex(['stored' => -1], ['background'=>1, 'socketTimeoutMS'=>-1]);
22+
$statementsCollection->createIndex(['lrs_id' => 1, 'stored' => 1], ['background'=>1, 'socketTimeoutMS'=>-1]);
23+
$statementsCollection->createIndex(['lrs_id' => 1, 'stored' => -1], ['background'=>1, 'socketTimeoutMS'=>-1]);
24+
25+
$statementsCursor = $statementsCollection->find();
26+
27+
$remaining = $statementsCursor->count();
28+
print($remaining . ' statements total' . PHP_EOL);
29+
30+
$maxBatchSize = 10000;
31+
32+
while($statementsCursor->hasNext()) {
33+
$batch = new MongoUpdateBatch($statementsCollection);
34+
$batchSize = 0;
35+
36+
while($batchSize < $maxBatchSize && $statementsCursor->hasNext()) {
37+
$batchSize++;
38+
$statement = $statementsCursor->next();
39+
$statementStored = new Carbon\Carbon($statement['statement']['stored']);
40+
41+
$query = [
42+
'q' => ['_id' => $statement['_id']],
43+
'u' => ['$set' => ["stored" => new \MongoDate($statementStored->timestamp, $statementStored->micro)]],
44+
'multi' => false,
45+
'upsert' => false,
46+
];
47+
48+
if(isset($statement['refs'])) {
49+
foreach ($statement['refs'] as $key => $refStatement) {
50+
if(isset($refStatement['timestamp']) && !$refStatement['timestamp'] instanceof MongoDate) {
51+
$timestamp = new Carbon\Carbon($refStatement['timestamp']);
52+
$query['u']['$set']['refs.'.$key.'.timestamp'] = new \MongoDate($timestamp->timestamp, $timestamp->micro);
53+
}
54+
if(isset($refStatement['stored']) && !$stored['stored'] instanceof MongoDate) {
55+
$stored = new Carbon\Carbon($refStatement['stored']);
56+
$query['u']['$set']['refs.'.$key.'.stored'] = new \MongoDate($stored->timestamp, $stored->micro);
57+
}
58+
}
59+
}
60+
61+
$batch->add((object) $query);
62+
}
63+
$batch->execute();
64+
$remaining -= $batchSize;
65+
66+
print($remaining . ' remaining' . PHP_EOL);
67+
}
68+
}
69+
70+
/**
71+
* Reverse the migrations.
72+
*
73+
* @return void
74+
*/
75+
public function down()
76+
{
77+
$db = \DB::getMongoDB();
78+
$statementsCollection = new MongoCollection($db, 'statements');
79+
80+
$statementsCollection->deleteIndex('stored');
81+
$statementsCollection->deleteIndex(['lrs_id' => 1, 'stored' => -1]);
82+
83+
$statementsCollection->update([], ['$unset' => ["stored" => ""]], ['multiple' => true]);
84+
85+
$statementsCursor = $statementsCollection->find();
86+
$remaining = $statementsCursor->count();
87+
print($remaining . ' statements total' . PHP_EOL);
88+
89+
$maxBatchSize = 10000;
90+
91+
while($statementsCursor->hasNext()) {
92+
$batch = new MongoUpdateBatch($statementsCollection);
93+
$batchSize = 0;
94+
$shouldExecute = false;
95+
96+
while($batchSize < $maxBatchSize && $statementsCursor->hasNext()) {
97+
$batchSize++;
98+
$statement = $statementsCursor->next();
99+
100+
if(isset($statement['refs'])) {
101+
$query = [
102+
'q' => ['_id' => $statement['_id']],
103+
'u' => ['$set' => []],
104+
'multi' => false,
105+
'upsert' => false,
106+
];
107+
foreach ($statement['refs'] as $key => $refStatement) {
108+
if(isset($refStatement['timestamp']) && $refStatement['timestamp'] instanceof MongoDate ) {
109+
$query['u']['$set']['refs.'.$key.'.timestamp'] = date('Y-m-d\TH:i:s.uP', $refStatement['timestamp']->sec);
110+
}
111+
if(isset($refStatement['stored']) && $refStatement['stored'] instanceof MongoDate ) {
112+
$query['u']['$set']['refs.'.$key.'.stored'] = date('Y-m-d\TH:i:s.uP', $refStatement['stored']->sec);
113+
}
114+
}
115+
116+
if(!empty($query['u']['$set'])) {
117+
$batch->add((object) $query);
118+
$shouldExecute = true;
119+
}
120+
}
121+
}
122+
123+
if($shouldExecute) $batch->execute();
124+
$remaining -= $batchSize;
125+
126+
print($remaining . ' remaining' . PHP_EOL);
127+
}
128+
}
129+
130+
}

app/locker/data/analytics/Analytics.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ private function setFilter(array $options) {
196196
* @return MongoDate object
197197
**/
198198
private function setMongoDate($date) {
199-
return new \MongoDate(strtotime($date));
199+
$carbon = new \Carbon\Carbon($date);
200+
return new \MongoDate($carbon->timestamp, $carbon->micro);
200201
}
201202

202203
/**

app/locker/repository/Report/EloquentRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,6 @@ public function statements($id, array $opts) {
105105
return (new QueryRepository)->where(
106106
$report->lrs_id,
107107
Helpers::replaceHtmlEntity($report->where)
108-
)->orderBy('statement.stored', 'DESC');
108+
)->orderBy('stored', 'DESC');
109109
}
110110
}

app/locker/repository/Statement/EloquentIndexer.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,24 @@ public function index(IndexOptions $opts) {
4242
return $this->addWhere($builder, 'context.registration', $value);
4343
},
4444
'since' => function ($value, $builder, IndexOptions $opts) {
45-
return $this->addWhere($builder, 'stored', $value, '>');
45+
$key = 'stored';
46+
$op = '>';
47+
return $builder->where(function ($query) use ($key, $value, $op) {
48+
$date = new \MongoDate(strtotime($value));
49+
return $query
50+
->orWhere($key, $op, $date)
51+
->orWhere('refs.'.$key, $op, $date);
52+
});
4653
},
4754
'until' => function ($value, $builder, IndexOptions $opts) {
48-
return $this->addWhere($builder, 'stored', $value, '<=');
55+
$key = 'stored';
56+
$op = '<=';
57+
return $builder->where(function ($query) use ($key, $value, $op) {
58+
$date = new \MongoDate(strtotime($value));
59+
return $query
60+
->orWhere($key, $op, $date)
61+
->orWhere('refs.'.$key, $op, $date);
62+
});
4963
},
5064
'active' => function ($value, $builder, IndexOptions $opts) {
5165
return $builder->where('active', $value);
@@ -133,7 +147,7 @@ public function format(Builder $builder, IndexOptions $opts) {
133147

134148
// Returns the models.
135149
return json_decode($builder
136-
->orderBy('statement.stored', $opts->getOpt('ascending') === true ? 'ASC' : 'DESC')
150+
->orderBy('stored', $opts->getOpt('ascending') === true ? 'ASC' : 'DESC')
137151
->skip($opts->getOpt('offset'))
138152
->take($opts->getOpt('limit'))
139153
->get()

app/locker/repository/Statement/EloquentInserter.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,17 @@ private function matchableStatement(\stdClass $statement) {
8585
* @return [String => Mixed] $model
8686
*/
8787
private function constructModel(\stdClass $statement, StoreOptions $opts) {
88+
$timestamp = new \Carbon\Carbon($statement->timestamp);
89+
$stored = new \Carbon\Carbon($statement->stored);
8890
return [
8991
'lrs' => ['_id' => $opts->getOpt('lrs_id')], // Deprecated.
9092
'lrs_id' => $opts->getOpt('lrs_id'),
9193
'client_id' => $opts->getOpt('client')->_id,
9294
'statement' => Helpers::replaceFullStop(json_decode(json_encode($statement), true)),
9395
'active' => false,
9496
'voided' => false,
95-
'timestamp' => new \MongoDate(strtotime($statement->timestamp))
96-
];
97+
'timestamp' => new \MongoDate($timestamp->timestamp, $timestamp->micro),
98+
'stored' => new \MongoDate($stored->timestamp, $stored->micro), ];
9799
}
98100

99101
/**

app/locker/repository/Statement/EloquentLinker.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ private function setRefs(\stdClass $statement, array $refs, StoreOptions $opts)
139139
->where('statement.id', $statement->id)
140140
->update([
141141
'refs' => array_map(function ($ref) {
142-
return Helpers::replaceFullStop(json_decode(json_encode($ref->statement), true));
142+
$statement = Helpers::replaceFullStop(json_decode(json_encode($ref->statement), true));
143+
$statement['stored'] = new \MongoDate( strtotime($statement['stored']));
144+
$statement['timestamp'] = new \MongoDate( strtotime($statement['timestamp']));
145+
return $statement;
143146
}, $refs)
144147
]);
145148
}

0 commit comments

Comments
 (0)