-
Notifications
You must be signed in to change notification settings - Fork 73
/
ReportSaver.scala
152 lines (127 loc) · 5.18 KB
/
ReportSaver.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
*************************************************************************************
* Copyright 2011 Normation SAS
*************************************************************************************
*
* This file is part of Rudder.
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
* Public License version 3, when you create a Related Module, this
* Related Module is not considered as a part of the work and may be
* distributed under the license agreement of your choice.
* A "Related Module" means a set of sources files including their
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
* Rudder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************************
*/
package com.normation.inventory.services.provisioning
import com.normation.inventory.domain.InventoryReport
import com.normation.utils.Control.pipeline
import net.liftweb.common.{Box,Full,Empty,Failure}
import net.liftweb.common.Loggable
/**
*
* This service is in charge to persist
* parsed and merged reports.
*
* In particular, this service has to deal with
* consistency problems (no transaction on
* LDAP backends...)
*
* Most likely, implementations of that service
* have to be pipelined so that pre-, post-,
* deffered- and triggered- action may be performed
* (logging comes to mind)
*
* The R parameter is the return type of the back-end.
* Ideally, it should be only diff actually applied to the back-end,
* but it could be the new entity is the store can not provide
* better information (LDAP can).
*/
trait ReportSaver[R] {
def save(report:InventoryReport) : Box[R]
}
/**
* Propose a standard implementation type fory ReportSaver
* based on pre- and post- process, and a "save" op in the
* middle
*/
trait PipelinedReportSaver[R] extends ReportSaver[R] with Loggable {
val preCommitPipeline:Seq[PreCommit]
val postCommitPipeline:Seq[PostCommit[R]]
/**
* Here comes the logic to actually save change in the Directory
* @param report
* @return
*/
def commitChange(report:InventoryReport) : Box[R]
override def save(report:InventoryReport) : Box[R] = {
val t0 = System.currentTimeMillis
for {
/*
* Firstly, we let the chance to third part contributor to
* modify the report to be save, make additional synchro,
* etc.
*
* An error here leads to the stop of the report saving
* process, so be *really* careful about your error management
*/
postPreCommitReport <- pipeline(preCommitPipeline, report){ (preCommit, currentReport) =>
try {
val t0 = System.currentTimeMillis
val res = preCommit(currentReport) ?~! "Error in preCommit pipeline with processor '%s', abort".format(preCommit.name)
val t1 = System.currentTimeMillis
logger.trace(s"Precommit '${preCommit.name}': ${t1-t0} ms")
res
} catch {
case ex:Exception => Failure("Exception in preCommit pipeline with processor '%s', abort".format(preCommit.name), Full(ex), Empty)
}
}
/*
* commit change - no rollback !
*/
t1 = System.currentTimeMillis
_ = logger.trace(s"Pre commit report: ${t1-t0} ms")
commitedChange <- try {
commitChange(postPreCommitReport)
} catch {
case ex:Exception => Failure(s"Exception when commiting inventory, abort: ${ex.getMessage}", Full(ex), Empty)
}
t2 = System.currentTimeMillis
_ = logger.trace(s"Commit report: ${t2-t1} ms")
/*
* now, post process report with third-party actions
*/
postPostCommitReport <- pipeline(postCommitPipeline, commitedChange) { (postCommit,currentChanges) =>
try {
postCommit(postPreCommitReport, currentChanges) ?~! "Error in postCommit pipeline with processor '%s'. The commit was done, we may be in a inconsistent state.".format(postCommit.name)
} catch {
case ex:Exception => Failure("Exception in postCommit pipeline with processor '%s'. The commit was done, we may be in a inconsistent state,".format(postCommit.name), Full(ex), Empty)
}
}
t3 = System.currentTimeMillis
_ = logger.trace(s"Post commit report: ${t3-t2} ms")
} yield {
postPostCommitReport
}
}
}