1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical.crm
21 
22 import java.net.URI
23 import java.nio.file.Path
24 
25 import cats.implicits._
26 import akka.http.scaladsl.Http
27 import akka.http.scaladsl.model._
28 import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
29 import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller
30 import akka.http.scaladsl.unmarshalling.Unmarshal
31 import akka.stream.scaladsl.{FileIO, Flow, Keep, Sink, Source, SourceQueueWithComplete}
32 import akka.stream.{ActorAttributes, OverflowStrategy, QueueOfferResult}
33 import grizzled.slf4j.Logging
34 import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport
35 import io.circe.syntax._
36 import io.circe.Printer
37 import org.make.api.extensions.MailJetConfigurationComponent
38 import org.make.api.technical.ActorSystemComponent
39 import org.make.api.technical.crm.BasicCrmResponse._
40 import org.make.api.technical.crm.CrmClient.{Account, Marketing, Transactional}
41 import org.make.core.Order
42 import org.make.core.technical.Pagination
43 
44 import scala.concurrent.{ExecutionContext, Future, Promise}
45 import scala.util.{Failure, Success, Try}
46 
47 trait DefaultCrmClientComponent extends CrmClientComponent with ErrorAccumulatingCirceSupport with Logging {
48   self: MailJetConfigurationComponent with ActorSystemComponent =>
49 
50   override lazy val crmClient: CrmClient = new DefaultCrmClient
51 
52   class DefaultCrmClient extends CrmClient {
53 
54     private val stringifyJson = Printer.noSpaces.copy(dropNullValues = false).print(_)
55     private lazy val url = new URI(mailJetConfiguration.url)
56     private val httpsPort: Int = 443
57     type Ctx = Promise[HttpResponse]
58 
59     lazy val httpFlow: Flow[(HttpRequest, Ctx), (Try[HttpResponse], Ctx), Http.HostConnectionPool] =
60       Http(actorSystem).cachedHostConnectionPoolHttps[Ctx](host = url.getHost, port = httpsPort)
61 
62     private lazy val bufferSize = mailJetConfiguration.httpBufferSize
63 
64     lazy val queue: SourceQueueWithComplete[(HttpRequest, Promise[HttpResponse])] = Source
65       .queue[(HttpRequest, Promise[HttpResponse])](bufferSize = bufferSize, OverflowStrategy.backpressure)
66       .via(httpFlow)
67       .withAttributes(ActorAttributes.dispatcher("make-api.mail-jet.dispatcher"))
68       .toMat(Sink.foreach {
69         case (Success(resp), p) => p.success(resp)
70         case (Failure(e), p)    => p.failure(e)
71       })(Keep.left)
72       .run()
73 
74     private lazy val campaignApiAuthorization = Authorization(
75       BasicHttpCredentials(mailJetConfiguration.campaignApiKey, mailJetConfiguration.campaignSecretKey)
76     )
77 
78     private lazy val transactionalApiAuthorization = Authorization(
79       BasicHttpCredentials(mailJetConfiguration.apiKey, mailJetConfiguration.secretKey)
80     )
81 
82     private val choseAccount: Account => Authorization = {
83       case Marketing     => campaignApiAuthorization
84       case Transactional => transactionalApiAuthorization
85     }
86 
87     import CrmClientException.RequestException._
88 
89     override def manageContactList(manageContactList: ManageManyContacts, account: Account)(
90       implicit executionContext: ExecutionContext
91     ): Future[ManageManyContactsResponse] = {
92       val request =
93         HttpRequest(
94           method = HttpMethods.POST,
95           uri = Uri(s"${mailJetConfiguration.url}/v3/REST/contact/managemanycontacts"),
96           headers = Seq(choseAccount(account)),
97           entity = HttpEntity(ContentTypes.`application/json`, stringifyJson(manageContactList.asJson))
98         )
99       runWithRetries(request, "manageContactList", ManageContactListException).flatMap(
100         Unmarshal(_).to[ManageManyContactsResponse]
101       )
102     }
103 
104     override def sendCsv(listId: String, csv: Path, account: Account)(
105       implicit executionContext: ExecutionContext
106     ): Future[SendCsvResponse] = {
107       val request = HttpRequest(
108         method = HttpMethods.POST,
109         uri = Uri(s"${mailJetConfiguration.url}/v3/DATA/contactslist/$listId/CSVData/application:octet-stream"),
110         headers = Seq(choseAccount(account)),
111         entity = HttpEntity(contentType = ContentTypes.`application/octet-stream`, data = FileIO.fromPath(csv))
112       )
113       runWithRetries(request, "sendCsv", SendCsvException).flatMap(Unmarshal(_).to[SendCsvResponse])
114     }
115 
116     override def manageContactListWithCsv(csvImport: CsvImport, account: Account)(
117       implicit executionContext: ExecutionContext
118     ): Future[ManageContactsWithCsvResponse] = {
119       val request =
120         HttpRequest(
121           method = HttpMethods.POST,
122           uri = Uri(s"${mailJetConfiguration.url}/v3/REST/csvimport"),
123           headers = Seq(choseAccount(account)),
124           entity = HttpEntity(ContentTypes.`application/json`, stringifyJson(csvImport.asJson))
125         )
126       runWithRetries(request, "manageContactListWithCsv", CsvImportException)
127         .flatMap(Unmarshal(_).to[ManageContactsWithCsvResponse])
128     }
129 
130     override def monitorCsvImport(jobId: Long, account: Account)(
131       implicit executionContext: ExecutionContext
132     ): Future[ManageContactsWithCsvResponse] = {
133       val request =
134         HttpRequest(
135           method = HttpMethods.GET,
136           uri = Uri(s"${mailJetConfiguration.url}/v3/REST/csvimport/$jobId"),
137           headers = Seq(choseAccount(account))
138         )
139       runWithRetries(request, "monitorCsvImport", MonitorCsvImportException)
140         .flatMap(Unmarshal(_).to[ManageContactsWithCsvResponse])
141     }
142 
143     override def sendEmail(message: SendMessages, account: Account)(
144       implicit executionContext: ExecutionContext
145     ): Future[SendEmailResponse] = {
146       val messagesWithErrorHandling = message.copy(messages = message.messages.map(
147         _.copy(templateErrorReporting = Some(
148           TemplateErrorReporting(
149             mailJetConfiguration.errorReportingRecipient,
150             Some(mailJetConfiguration.errorReportingRecipientName)
151           )
152         )
153         )
154       )
155       )
156 
157       val request = HttpRequest(
158         method = HttpMethods.POST,
159         uri = Uri(s"${mailJetConfiguration.url}/v3.1/send"),
160         headers = Seq(choseAccount(account)),
161         entity = HttpEntity(ContentTypes.`application/json`, stringifyJson(messagesWithErrorHandling.asJson))
162       )
163       runWithRetries(request, "sendEmail", SendEmailException).flatMap(Unmarshal(_).to[SendEmailResponse])
164     }
165 
166     override def getUsersInformationMailFromList(
167       listId: Option[String] = None,
168       sort: Option[String] = None,
169       order: Option[Order] = None,
170       countOnly: Option[Boolean] = None,
171       limit: Pagination.Limit,
172       offset: Pagination.Offset = Pagination.Offset(0),
173       account: Account
174     )(implicit executionContext: ExecutionContext): Future[ContactsResponse] = {
175       val sortQuery: Option[String] = (sort, order) match {
176         case (Some(s), Some(o)) => Some(s"$s+$o")
177         case (Some(s), _)       => Some(s)
178         case _                  => None
179       }
180       val params: Map[String, Option[String]] = Map(
181         "ContactsList" -> listId,
182         "Sort" -> sortQuery,
183         "Limit" -> Some(limit.toString),
184         "Offset" -> Some(offset.toString),
185         "countOnly" -> countOnly.map(bool => if (bool) "1" else "0")
186       )
187       val paramsQuery = params.collect { case (k, Some(v)) => s"$k=$v" }.mkString("&")
188       val request = HttpRequest(
189         method = HttpMethods.GET,
190         uri = Uri(s"${mailJetConfiguration.url}/v3/REST/contact?$paramsQuery"),
191         headers = Seq(choseAccount(account))
192       )
193       runWithRetries(request, "getUsersInformationMailFromList", GetUsersInformationMailFromListException)
194         .flatMap(Unmarshal(_).to[ContactsResponse])
195     }
196 
197     override def getContactsProperties(offset: Int, limit: Pagination.Limit, account: Account)(
198       implicit executionContext: ExecutionContext
199     ): Future[GetMailjetContactProperties] = {
200       val paramsQuery = s"Limit=${limit.value.value}&Offset=$offset"
201       val request = HttpRequest(
202         method = HttpMethods.GET,
203         uri = Uri(s"${mailJetConfiguration.url}/v3/REST/contactdata?$paramsQuery"),
204         headers = Seq(choseAccount(account))
205       )
206       runWithRetries(request, "getContactsProperties", GetContactsPropertiesException)
207         .flatMap(Unmarshal(_).to[GetMailjetContactProperties])
208     }
209 
210     private def getContactByMailOrContactId(identifier: String, account: Account)(
211       implicit executionContext: ExecutionContext
212     ): Future[ContactsResponse] = {
213       val request = HttpRequest(
214         method = HttpMethods.GET,
215         uri = Uri(s"${mailJetConfiguration.url}/v3/REST/contact/$identifier"),
216         headers = Seq(choseAccount(account))
217       )
218       runWithRetries(request, "getContactByMailOrContactId", GetUsersMailFromListException)
219         .flatMap(Unmarshal(_).to[ContactsResponse])
220     }
221 
222     override def deleteContactById(contactId: String, account: Account)(
223       implicit executionContext: ExecutionContext
224     ): Future[Unit] = {
225       val request = HttpRequest(
226         method = HttpMethods.DELETE,
227         uri = Uri(s"${mailJetConfiguration.url}/v4/contacts/$contactId"),
228         headers = Seq(choseAccount(account))
229       )
230       runWithRetries(request, "deleteContactById", DeleteUserException).map(_.discardBytes()).void.recoverWith {
231         case error: DeleteUserException if error.code == StatusCodes.NotFound =>
232           logger.error(s"deleteContactById failed with status ${error.code}: ${error.response}")
233           Future.unit
234       }
235     }
236 
237     override def deleteContactByEmail(email: String, account: Account)(
238       implicit executionContext: ExecutionContext
239     ): Future[Unit] = {
240       getContactByMailOrContactId(email, account).flatMap {
241         case BasicCrmResponse(_, _, head :: _) =>
242           val id = head.id.toString
243           deleteContactById(id, account)
244         case _ => Future.unit
245       }.recoverWith {
246         case e: CrmClientException =>
247           logger.error(e.message)
248           Future.unit
249         case e => Future.failed(e)
250       }
251     }
252 
253     private def runWithRetries(
254       request: HttpRequest,
255       id: String,
256       exceptionFn: (StatusCode, String) => CrmClientException.RequestException,
257       maxRetries: Int = 5
258     )(implicit ec: ExecutionContext): Future[ResponseEntity] = {
259 
260       @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
261       def loop(retries: Int): Future[HttpResponse] = {
262         val promise = Promise[HttpResponse]()
263         queue.offer((request, promise)).flatMap {
264           case QueueOfferResult.Enqueued =>
265             promise.future.flatMap {
266               case HttpResponse(StatusCodes.InternalServerError, _, entity, _) if retries > 0 =>
267                 Unmarshal(entity).to[String].flatMap { response =>
268                   logger.warn(s"Error '$response' from Mailjet, $retries retries left")
269                   loop(retries - 1)
270                 }
271               case other => Future.successful(other)
272             }.recoverWith {
273               case error =>
274                 if (retries > 0) {
275                   logger.error(s"Mailjet request $request failed with:", error)
276                   loop(retries - 1)
277                 } else {
278                   Future.failed(error)
279                 }
280             }
281           case QueueOfferResult.Dropped     => Future.failed(CrmClientException.QueueException.QueueOverflowed)
282           case QueueOfferResult.Failure(ex) => Future.failed(ex)
283           case QueueOfferResult.QueueClosed => Future.failed(CrmClientException.QueueException.QueueClosed)
284         }
285       }
286       loop(maxRetries).flatMap({
287         case HttpResponse(code, _, entity, _) if code.isSuccess => Future.successful(entity)
288         case HttpResponse(code, _, entity, _) =>
289           Unmarshal(entity)
290             .to[String]
291             .flatMap(response => {
292               val exception: Exception = code match {
293                 case StatusCodes.TooManyRequests => QuotaExceeded(id, response)
294                 case code                        => exceptionFn(code, response)
295               }
296               Future.failed(exception)
297             })
298       })
299     }
300   }
301 }
302 
303 final case class QuotaExceeded(method: String, message: String) extends Exception(message)
304 
305 sealed abstract class CrmClientException(val message: String) extends Exception(message) with Product with Serializable
306 
307 object CrmClientException {
308 
309   sealed abstract class QueueException(message: String) extends CrmClientException(message)
310 
311   sealed abstract class RequestException(action: String, code: StatusCode, response: String)
312       extends CrmClientException(s"$action failed with status $code: $response")
313 
314   object QueueException {
315 
316     case object QueueOverflowed extends QueueException("Queue overflowed. Try again later.")
317 
318     case object QueueClosed
319         extends QueueException("Queue was closed (pool shut down) while running the request. Try again later.")
320 
321   }
322 
323   object RequestException {
324 
325     final case class ManageContactListException(code: StatusCode, response: String)
326         extends RequestException("manageContactList", code, response)
327 
328     final case class SendCsvException(code: StatusCode, response: String)
329         extends RequestException("send csv", code, response)
330 
331     final case class CsvImportException(code: StatusCode, response: String)
332         extends RequestException("csv import", code, response)
333 
334     final case class MonitorCsvImportException(code: StatusCode, response: String)
335         extends RequestException("monitor csv import", code, response)
336 
337     final case class SendEmailException(code: StatusCode, response: String)
338         extends RequestException("send email", code, response)
339 
340     final case class GetUsersInformationMailFromListException(code: StatusCode, response: String)
341         extends RequestException("getUsersInformationMailFromList", code, response)
342 
343     final case class GetContactsPropertiesException(code: StatusCode, response: String)
344         extends RequestException("getContactsProperties", code, response)
345 
346     final case class ManageContactListJobDetailsException(code: StatusCode, response: String)
347         extends RequestException("manageContactListJobDetails", code, response)
348 
349     final case class GetUsersMailFromListException(code: StatusCode, response: String)
350         extends RequestException("getUsersMailFromList", code, response)
351 
352     final case class DeleteUserException(code: StatusCode, response: String)
353         extends RequestException("deleteContactById", code, response)
354   }
355 }
Line Stmt Id Pos Tree Symbol Tests Code
54 24076 2185 - 2239 Apply io.circe.Printer.print org.make.api.technical.crm.crmclientcomponenttest io.circe.Printer.noSpaces.copy(false, io.circe.Printer.noSpaces.copy$default$2, io.circe.Printer.noSpaces.copy$default$3, io.circe.Printer.noSpaces.copy$default$4, io.circe.Printer.noSpaces.copy$default$5, io.circe.Printer.noSpaces.copy$default$6, io.circe.Printer.noSpaces.copy$default$7, io.circe.Printer.noSpaces.copy$default$8, io.circe.Printer.noSpaces.copy$default$9, io.circe.Printer.noSpaces.copy$default$10, io.circe.Printer.noSpaces.copy$default$11, io.circe.Printer.noSpaces.copy$default$12, io.circe.Printer.noSpaces.copy$default$13, io.circe.Printer.noSpaces.copy$default$14, io.circe.Printer.noSpaces.copy$default$15, io.circe.Printer.noSpaces.copy$default$16, io.circe.Printer.noSpaces.copy$default$17, io.circe.Printer.noSpaces.copy$default$18, io.circe.Printer.noSpaces.copy$default$19, io.circe.Printer.noSpaces.copy$default$20, io.circe.Printer.noSpaces.copy$default$21).print(x$1)
56 22722 2334 - 2337 Literal <nosymbol> org.make.api.technical.crm.crmclientcomponenttest 443
93 24142 3889 - 4188 Apply akka.http.scaladsl.model.HttpRequest.apply org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.POST, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact/managemanycontacts"): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.ManageManyContacts](manageContactList).asJson(crm.this.ManageManyContacts.encoder))), akka.http.scaladsl.model.HttpRequest.apply$default$5)
93 26695 3889 - 3889 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.HttpRequest.apply$default$5
94 26550 3921 - 3937 Select akka.http.scaladsl.model.HttpMethods.POST org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.HttpMethods.POST
95 24298 3955 - 4025 Apply akka.http.scaladsl.model.Uri.apply org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact/managemanycontacts"): String))
96 26864 4047 - 4073 Apply scala.collection.SeqFactory.Delegate.apply org.make.api.technical.crm.crmclientcomponenttest scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
96 28131 4051 - 4072 Apply scala.Function1.apply org.make.api.technical.crm.crmclientcomponenttest DefaultCrmClient.this.choseAccount.apply(account)
97 23858 4138 - 4177 Apply scala.Function1.apply org.make.api.technical.crm.crmclientcomponenttest DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.ManageManyContacts](manageContactList).asJson(crm.this.ManageManyContacts.encoder))
97 24603 4105 - 4136 Select akka.http.scaladsl.model.ContentTypes.application/json org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.ContentTypes.application/json
97 26195 4152 - 4176 ApplyToImplicitArgs io.circe.syntax.EncoderOps.asJson org.make.api.technical.crm.crmclientcomponenttest io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.ManageManyContacts](manageContactList).asJson(crm.this.ManageManyContacts.encoder)
97 22636 4170 - 4170 Select org.make.api.technical.crm.ManageManyContacts.encoder org.make.api.technical.crm.crmclientcomponenttest crm.this.ManageManyContacts.encoder
97 22735 4094 - 4178 Apply akka.http.scaladsl.model.HttpEntity.apply org.make.api.technical.crm.crmclientcomponenttest akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.ManageManyContacts](manageContactList).asJson(crm.this.ManageManyContacts.encoder)))
99 28144 4195 - 4336 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.technical.crm.crmclientcomponenttest DefaultCrmClient.this.runWithRetries(request, "manageContactList", CrmClientException.RequestException.ManageContactListException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.ManageManyContactsResponse](((x$2: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$2).to[org.make.api.technical.crm.BasicCrmResponse.ManageManyContactsResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.ManageManyContactsResponse](org.make.api.technical.crm.BasicCrmResponse.manageManyContactsResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
107 28119 4520 - 4520 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
107 25761 4520 - 4846 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.POST, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/DATA/contactslist/").+(listId).+("/CSVData/application:octet-stream"): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/octet-stream, akka.stream.scaladsl.FileIO.fromPath(csv, akka.stream.scaladsl.FileIO.fromPath$default$2)), akka.http.scaladsl.model.HttpRequest.apply$default$5)
108 25746 4550 - 4566 Select akka.http.scaladsl.model.HttpMethods.POST akka.http.scaladsl.model.HttpMethods.POST
109 24616 4582 - 4679 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/DATA/contactslist/").+(listId).+("/CSVData/application:octet-stream"): String))
110 26029 4699 - 4725 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
110 22565 4703 - 4724 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
111 23873 4769 - 4808 Select akka.http.scaladsl.model.ContentTypes.application/octet-stream akka.http.scaladsl.model.ContentTypes.application/octet-stream
111 26708 4817 - 4837 Apply akka.stream.scaladsl.FileIO.fromPath akka.stream.scaladsl.FileIO.fromPath(csv, akka.stream.scaladsl.FileIO.fromPath$default$2)
111 24151 4744 - 4838 Apply akka.http.scaladsl.model.HttpEntity.apply akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/octet-stream, akka.stream.scaladsl.FileIO.fromPath(csv, akka.stream.scaladsl.FileIO.fromPath$default$2))
111 22658 4824 - 4824 Select akka.stream.scaladsl.FileIO.fromPath$default$2 akka.stream.scaladsl.FileIO.fromPath$default$2
113 24762 4853 - 4947 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "sendCsv", CrmClientException.RequestException.SendCsvException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.SendCsvResponse](((x$3: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$3).to[org.make.api.technical.crm.SendCsvResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.SendCsvResponse](crm.this.SendCsvResponse.decoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
120 22581 5165 - 5165 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
120 26190 5165 - 5439 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.POST, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/csvimport"): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.CsvImport](csvImport).asJson(crm.this.CsvImport.encoder))), akka.http.scaladsl.model.HttpRequest.apply$default$5)
121 22573 5197 - 5213 Select akka.http.scaladsl.model.HttpMethods.POST akka.http.scaladsl.model.HttpMethods.POST
122 26037 5231 - 5284 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/csvimport"): String))
123 22671 5306 - 5332 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
123 24010 5310 - 5331 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
124 24770 5353 - 5429 Apply akka.http.scaladsl.model.HttpEntity.apply akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.CsvImport](csvImport).asJson(crm.this.CsvImport.encoder)))
124 25894 5397 - 5428 Apply scala.Function1.apply DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.CsvImport](csvImport).asJson(crm.this.CsvImport.encoder))
124 28128 5411 - 5427 ApplyToImplicitArgs io.circe.syntax.EncoderOps.asJson io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.CsvImport](csvImport).asJson(crm.this.CsvImport.encoder)
124 24463 5421 - 5421 Select org.make.api.technical.crm.CsvImport.encoder crm.this.CsvImport.encoder
124 26637 5364 - 5395 Select akka.http.scaladsl.model.ContentTypes.application/json akka.http.scaladsl.model.ContentTypes.application/json
127 24020 5446 - 5582 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "manageContactListWithCsv", CrmClientException.RequestException.CsvImportException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](((x$4: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$4).to[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](org.make.api.technical.crm.BasicCrmResponse.manageContactsWithCsvResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
134 24525 5783 - 5783 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
134 22511 5783 - 5966 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/csvimport/").+(jobId): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
134 25899 5783 - 5783 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
135 27589 5815 - 5830 Select akka.http.scaladsl.model.HttpMethods.GET akka.http.scaladsl.model.HttpMethods.GET
136 26648 5848 - 5908 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/csvimport/").+(jobId): String))
137 28060 5930 - 5956 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
137 24471 5934 - 5955 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
140 26199 5973 - 6108 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "monitorCsvImport", CrmClientException.RequestException.MonitorCsvImportException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](((x$5: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$5).to[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.ManageContactsWithCsvResponse](org.make.api.technical.crm.BasicCrmResponse.manageContactsWithCsvResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
146 24381 6318 - 6318 Select org.make.api.technical.crm.SendMessages.copy$default$4 message.copy$default$4
146 23888 6334 - 6600 Apply scala.collection.IterableOps.map message.messages.map[org.make.api.technical.crm.SendEmail](((x$6: org.make.api.technical.crm.SendEmail) => { <artifact> val x$1: Some[org.make.api.technical.crm.TemplateErrorReporting] @scala.reflect.internal.annotations.uncheckedBounds = scala.Some.apply[org.make.api.technical.crm.TemplateErrorReporting](TemplateErrorReporting.apply(DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipient, scala.Some.apply[String](DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipientName))); <artifact> val x$2: Option[org.make.api.technical.crm.Recipient] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$1; <artifact> val x$3: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$2; <artifact> val x$4: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$3; <artifact> val x$5: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$4; <artifact> val x$6: Option[Boolean] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$5; <artifact> val x$7: Option[Int] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$6; <artifact> val x$8: Option[Map[String,String]] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$7; <artifact> val x$9: Seq[org.make.api.technical.crm.Recipient] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$8; <artifact> val x$10: Option[Map[String,String]] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$9; <artifact> val x$11: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$10; <artifact> val x$12: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$11; <artifact> val x$13: Option[String] @scala.reflect.internal.annotations.uncheckedBounds = x$6.copy$default$12; x$6.copy(x$2, x$3, x$4, x$5, x$6, x$7, x$8, x$9, x$10, x$11, x$12, x$13, x$1) }))
146 28202 6310 - 6608 Apply org.make.api.technical.crm.SendMessages.copy message.copy(x$15, x$16, x$14, x$17)
146 27535 6318 - 6318 Select org.make.api.technical.crm.SendMessages.copy$default$1 message.copy$default$1
146 26434 6318 - 6318 Select org.make.api.technical.crm.SendMessages.copy$default$2 message.copy$default$2
147 24460 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$8 x$6.copy$default$8
147 23482 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$11 x$6.copy$default$11
147 22495 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$12 x$6.copy$default$12
147 26421 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$7 x$6.copy$default$7
147 24537 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$2 x$6.copy$default$2
147 26346 6364 - 6592 Apply org.make.api.technical.crm.SendEmail.copy x$6.copy(x$2, x$3, x$4, x$5, x$6, x$7, x$8, x$9, x$10, x$11, x$12, x$13, x$1)
147 28068 6396 - 6582 Apply scala.Some.apply scala.Some.apply[org.make.api.technical.crm.TemplateErrorReporting](TemplateErrorReporting.apply(DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipient, scala.Some.apply[String](DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipientName)))
147 23962 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$5 x$6.copy$default$5
147 26133 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$4 x$6.copy$default$4
147 25663 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$1 x$6.copy$default$1
147 27613 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$6 x$6.copy$default$6
147 25675 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$10 x$6.copy$default$10
147 22343 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$3 x$6.copy$default$3
147 27995 6366 - 6366 Select org.make.api.technical.crm.SendEmail.copy$default$9 x$6.copy$default$9
148 24239 6412 - 6572 Apply org.make.api.technical.crm.TemplateErrorReporting.apply TemplateErrorReporting.apply(DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipient, scala.Some.apply[String](DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipientName))
149 23956 6448 - 6492 Select org.make.api.extensions.MailJetConfiguration.errorReportingRecipient DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipient
150 26492 6506 - 6560 Apply scala.Some.apply scala.Some.apply[String](DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipientName)
150 27603 6511 - 6559 Select org.make.api.extensions.MailJetConfiguration.errorReportingRecipientName DefaultCrmClientComponent.this.mailJetConfiguration.errorReportingRecipientName
157 23424 6630 - 6902 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.POST, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3.1/send"): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.SendMessages](messagesWithErrorHandling).asJson(crm.this.SendMessages.encoder))), akka.http.scaladsl.model.HttpRequest.apply$default$5)
157 25831 6630 - 6630 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
158 25688 6660 - 6676 Select akka.http.scaladsl.model.HttpMethods.POST akka.http.scaladsl.model.HttpMethods.POST
159 23414 6692 - 6737 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3.1/send"): String))
160 22506 6761 - 6782 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
160 26278 6757 - 6783 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
161 23951 6813 - 6844 Select akka.http.scaladsl.model.ContentTypes.application/json akka.http.scaladsl.model.ContentTypes.application/json
161 28212 6802 - 6894 Apply akka.http.scaladsl.model.HttpEntity.apply akka.http.scaladsl.model.HttpEntity.apply(akka.http.scaladsl.model.ContentTypes.application/json, DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.SendMessages](messagesWithErrorHandling).asJson(crm.this.SendMessages.encoder)))
161 27551 6886 - 6886 Select org.make.api.technical.crm.SendMessages.encoder crm.this.SendMessages.encoder
161 25505 6860 - 6892 ApplyToImplicitArgs io.circe.syntax.EncoderOps.asJson io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.SendMessages](messagesWithErrorHandling).asJson(crm.this.SendMessages.encoder)
161 24394 6846 - 6893 Apply scala.Function1.apply DefaultCrmClient.this.stringifyJson.apply(io.circe.syntax.`package`.EncoderOps[org.make.api.technical.crm.SendMessages](messagesWithErrorHandling).asJson(crm.this.SendMessages.encoder))
163 22432 6909 - 7009 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "sendEmail", CrmClientException.RequestException.SendEmailException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.SendEmailResponse](((x$7: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$7).to[org.make.api.technical.crm.SendEmailResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.SendEmailResponse](crm.this.SendEmailResponse.decoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
176 26289 7501 - 7515 Apply scala.Some.apply scala.Some.apply[String](("".+(s).+("+").+(o): String))
177 23959 7551 - 7558 Apply scala.Some.apply scala.Some.apply[String](s)
178 27682 7594 - 7598 Select scala.None scala.None
180 27830 7655 - 7883 Apply scala.collection.MapFactory.apply scala.Predef.Map.apply[String, Option[String]](scala.Predef.ArrowAssoc[String]("ContactsList").->[Option[String]](listId), scala.Predef.ArrowAssoc[String]("Sort").->[Option[String]](sortQuery), scala.Predef.ArrowAssoc[String]("Limit").->[Some[String]](scala.Some.apply[String](limit.toString())), scala.Predef.ArrowAssoc[String]("Offset").->[Some[String]](scala.Some.apply[String](offset.toString())), scala.Predef.ArrowAssoc[String]("countOnly").->[Option[String]](countOnly.map[String](((bool: Boolean) => if (bool) "1" else "0"))))
181 25520 7668 - 7692 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("ContactsList").->[Option[String]](listId)
182 24316 7702 - 7721 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("Sort").->[Option[String]](sortQuery)
183 22441 7731 - 7762 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("Limit").->[Some[String]](scala.Some.apply[String](limit.toString()))
183 25841 7747 - 7761 Apply org.make.core.technical.Pagination.Limit.toString limit.toString()
183 27990 7731 - 7738 Literal <nosymbol> "Limit"
183 23399 7742 - 7762 Apply scala.Some.apply scala.Some.apply[String](limit.toString())
184 26299 7772 - 7780 Literal <nosymbol> "Offset"
184 23882 7789 - 7804 Apply org.make.core.technical.Pagination.Offset.toString offset.toString()
184 25287 7772 - 7805 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("Offset").->[Some[String]](scala.Some.apply[String](offset.toString()))
184 27691 7784 - 7805 Apply scala.Some.apply scala.Some.apply[String](offset.toString())
185 24325 7815 - 7826 Literal <nosymbol> "countOnly"
185 23891 7815 - 7875 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("countOnly").->[Option[String]](countOnly.map[String](((bool: Boolean) => if (bool) "1" else "0")))
185 27999 7862 - 7865 Literal <nosymbol> "1"
185 23411 7871 - 7874 Literal <nosymbol> "0"
185 27155 7871 - 7874 Block <nosymbol> "0"
185 25770 7862 - 7865 Block <nosymbol> "1"
185 26066 7830 - 7875 Apply scala.Option.map countOnly.map[String](((bool: Boolean) => if (bool) "1" else "0"))
187 25298 7908 - 7970 Apply scala.collection.IterableOnceOps.mkString params.collect[String](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[(String, Option[String]),String] with java.io.Serializable { def <init>(): <$anon: ((String, Option[String])) => String> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: (String, Option[String]), B1 >: String](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[(String, Option[String])]: (String, Option[String])): (String, Option[String]) @unchecked) match { case (_1: String, _2: Option[String]): (String, Option[String])((k @ _), (value: String): Some[String]((v @ _))) => ("".+(k).+("=").+(v): String) case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: (String, Option[String])): Boolean = ((x1.asInstanceOf[(String, Option[String])]: (String, Option[String])): (String, Option[String]) @unchecked) match { case (_1: String, _2: Option[String]): (String, Option[String])((k @ _), (value: String): Some[String]((v @ _))) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[(String, Option[String]),String])).mkString("&")
188 27165 7991 - 7991 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
188 26285 7991 - 7991 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
188 23817 7991 - 8170 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact?").+(paramsQuery): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
189 24178 8021 - 8036 Select akka.http.scaladsl.model.HttpMethods.GET akka.http.scaladsl.model.HttpMethods.GET
190 27926 8052 - 8116 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact?").+(paramsQuery): String))
191 23707 8136 - 8162 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
191 25779 8140 - 8161 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
194 27841 8177 - 8329 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "getUsersInformationMailFromList", CrmClientException.RequestException.GetUsersInformationMailFromListException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](((x$8: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$8).to[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](org.make.api.technical.crm.BasicCrmResponse.contactsResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
201 23715 8619 - 8619 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
201 26208 8619 - 8802 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contactdata?").+(paramsQuery): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
201 27174 8619 - 8619 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
202 25307 8649 - 8664 Select akka.http.scaladsl.model.HttpMethods.GET akka.http.scaladsl.model.HttpMethods.GET
203 24312 8680 - 8748 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contactdata?").+(paramsQuery): String))
204 28149 8772 - 8793 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
204 25705 8768 - 8794 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
207 24035 8809 - 8952 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "getContactsProperties", CrmClientException.RequestException.GetContactsPropertiesException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.GetMailjetContactProperties](((x$9: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$9).to[org.make.api.technical.crm.BasicCrmResponse.GetMailjetContactProperties](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.GetMailjetContactProperties](org.make.api.technical.crm.BasicCrmResponse.getMailjetContactPropertiesResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
213 23729 9149 - 9149 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
213 27308 9149 - 9327 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.GET, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact/").+(identifier): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
213 25767 9149 - 9149 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
214 27770 9179 - 9194 Select akka.http.scaladsl.model.HttpMethods.GET akka.http.scaladsl.model.HttpMethods.GET
215 25609 9210 - 9273 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v3/REST/contact/").+(identifier): String))
216 28078 9293 - 9319 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
216 23275 9297 - 9318 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
219 26223 9334 - 9471 ApplyToImplicitArgs scala.concurrent.Future.flatMap DefaultCrmClient.this.runWithRetries(request, "getContactByMailOrContactId", CrmClientException.RequestException.GetUsersMailFromListException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).flatMap[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](((x$10: akka.http.scaladsl.model.ResponseEntity) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](x$10).to[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](DefaultCrmClientComponent.this.unmarshaller[org.make.api.technical.crm.BasicCrmResponse.ContactsResponse](org.make.api.technical.crm.BasicCrmResponse.contactsResponseDecoder), executionContext, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext)
225 23487 9646 - 9822 Apply akka.http.scaladsl.model.HttpRequest.apply akka.http.scaladsl.model.HttpRequest.apply(akka.http.scaladsl.model.HttpMethods.DELETE, akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v4/contacts/").+(contactId): String)), scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account)), akka.http.scaladsl.model.HttpRequest.apply$default$4, akka.http.scaladsl.model.HttpRequest.apply$default$5)
225 25687 9646 - 9646 Select akka.http.scaladsl.model.HttpRequest.apply$default$5 akka.http.scaladsl.model.HttpRequest.apply$default$5
225 28088 9646 - 9646 Select akka.http.scaladsl.model.HttpRequest.apply$default$4 akka.http.scaladsl.model.HttpRequest.apply$default$4
226 23972 9676 - 9694 Select akka.http.scaladsl.model.HttpMethods.DELETE akka.http.scaladsl.model.HttpMethods.DELETE
227 27621 9710 - 9768 Apply akka.http.scaladsl.model.Uri.apply akka.http.scaladsl.model.Uri.apply(("".+(DefaultCrmClientComponent.this.mailJetConfiguration.url).+("/v4/contacts/").+(contactId): String))
228 25619 9792 - 9813 Apply scala.Function1.apply DefaultCrmClient.this.choseAccount.apply(account)
228 23195 9788 - 9814 Apply scala.collection.SeqFactory.Delegate.apply scala.`package`.Seq.apply[akka.http.scaladsl.model.headers.Authorization](DefaultCrmClient.this.choseAccount.apply(account))
230 27322 9829 - 10143 ApplyToImplicitArgs scala.concurrent.Future.recoverWith cats.implicits.toFunctorOps[scala.concurrent.Future, akka.http.scaladsl.model.HttpMessage.DiscardedEntity](DefaultCrmClient.this.runWithRetries(request, "deleteContactById", CrmClientException.RequestException.DeleteUserException, DefaultCrmClient.this.runWithRetries$default$4)(executionContext).map[akka.http.scaladsl.model.HttpMessage.DiscardedEntity](((x$11: akka.http.scaladsl.model.ResponseEntity) => model.this.HttpEntity.HttpEntityScalaDSLSugar(x$11).discardBytes()(stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem))))(executionContext))(cats.implicits.catsStdInstancesForFuture(executionContext)).void.recoverWith[Unit](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Throwable,scala.concurrent.Future[Unit]] with java.io.Serializable { def <init>(): <$anon: Throwable => scala.concurrent.Future[Unit]> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: Throwable, B1 >: scala.concurrent.Future[Unit]](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (error @ (_: org.make.api.technical.crm.CrmClientException.RequestException.DeleteUserException)) if error.code.==(akka.http.scaladsl.model.StatusCodes.NotFound) => { DefaultCrmClientComponent.this.logger.error(("deleteContactById failed with status ".+(error.code).+(": ").+(error.response): String)); scala.concurrent.Future.unit } case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: Throwable): Boolean = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (error @ (_: org.make.api.technical.crm.CrmClientException.RequestException.DeleteUserException)) if error.code.==(akka.http.scaladsl.model.StatusCodes.NotFound) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[Throwable,scala.concurrent.Future[Unit]]))(executionContext)
245 25083 10303 - 10672 ApplyToImplicitArgs scala.concurrent.Future.recoverWith DefaultCrmClient.this.getContactByMailOrContactId(email, account)(executionContext).flatMap[Unit](((x0$1: org.make.api.technical.crm.BasicCrmResponse.ContactsResponse) => x0$1 match { case (count: Int, total: Int, data: Seq[org.make.api.technical.crm.ContactDataResponse]): org.make.api.technical.crm.BasicCrmResponse[org.make.api.technical.crm.ContactDataResponse](_, _, (head: org.make.api.technical.crm.ContactDataResponse, next: List[org.make.api.technical.crm.ContactDataResponse]): scala.collection.immutable.::[org.make.api.technical.crm.ContactDataResponse]((head @ _), _)) => { val id: String = head.id.toString(); DefaultCrmClient.this.deleteContactById(id, account)(executionContext) } case _ => scala.concurrent.Future.unit }))(executionContext).recoverWith[Unit](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Throwable,scala.concurrent.Future[Unit]] with java.io.Serializable { def <init>(): <$anon: Throwable => scala.concurrent.Future[Unit]> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: Throwable, B1 >: scala.concurrent.Future[Unit]](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ (_: org.make.api.technical.crm.CrmClientException)) => { DefaultCrmClientComponent.this.logger.error(e.message); scala.concurrent.Future.unit } case (e @ _) => scala.concurrent.Future.failed[Nothing](e) case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: Throwable): Boolean = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (e @ (_: org.make.api.technical.crm.CrmClientException)) => true case (e @ _) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[Throwable,scala.concurrent.Future[Unit]]))(executionContext)
262 23811 11073 - 11096 Apply scala.concurrent.Promise.apply org.make.api.technical.crm.crmclientcomponenttest scala.concurrent.Promise.apply[akka.http.scaladsl.model.HttpResponse]()
263 27629 11105 - 12184 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.technical.crm.crmclientcomponenttest DefaultCrmClient.this.queue.offer(scala.Tuple2.apply[akka.http.scaladsl.model.HttpRequest, scala.concurrent.Promise[akka.http.scaladsl.model.HttpResponse]](request, promise)).flatMap[akka.http.scaladsl.model.HttpResponse](((x0$1: akka.stream.QueueOfferResult) => x0$1 match { case akka.stream.QueueOfferResult.Enqueued => promise.future.flatMap[akka.http.scaladsl.model.HttpResponse](((x0$2: akka.http.scaladsl.model.HttpResponse) => x0$2 match { case akka.http.scaladsl.model.HttpResponse.unapply(<unapply-selector>) <unapply> (akka.http.scaladsl.model.StatusCodes.InternalServerError, _, (entity @ _), _) if retries.>(0) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](entity).to[String](akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller, ec, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem)).flatMap[akka.http.scaladsl.model.HttpResponse](((response: String) => { DefaultCrmClientComponent.this.logger.warn(("Error \'".+(response).+("\' from Mailjet, ").+(retries).+(" retries left"): String)); loop(retries.-(1)) }))(ec) case (other @ _) => scala.concurrent.Future.successful[akka.http.scaladsl.model.HttpResponse](other) }))(ec).recoverWith[akka.http.scaladsl.model.HttpResponse](({ @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Throwable,scala.concurrent.Future[akka.http.scaladsl.model.HttpResponse]] with java.io.Serializable { def <init>(): <$anon: Throwable => scala.concurrent.Future[akka.http.scaladsl.model.HttpResponse]> = { $anonfun.super.<init>(); () }; final override def applyOrElse[A1 <: Throwable, B1 >: scala.concurrent.Future[akka.http.scaladsl.model.HttpResponse]](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (error @ _) => if (retries.>(0)) { DefaultCrmClientComponent.this.logger.error(("Mailjet request ".+(request).+(" failed with:"): String), error); loop(retries.-(1)) } else scala.concurrent.Future.failed[Nothing](error) case (defaultCase$ @ _) => default.apply(x1) }; final def isDefinedAt(x1: Throwable): Boolean = ((x1.asInstanceOf[Throwable]: Throwable): Throwable @unchecked) match { case (error @ _) => true case (defaultCase$ @ _) => false } }; new $anonfun() }: PartialFunction[Throwable,scala.concurrent.Future[akka.http.scaladsl.model.HttpResponse]]))(ec) case akka.stream.QueueOfferResult.Dropped => scala.concurrent.Future.failed[Nothing](CrmClientException.QueueException.QueueOverflowed) case (cause: Throwable): akka.stream.QueueOfferResult.Failure((ex @ _)) => scala.concurrent.Future.failed[Nothing](ex) case akka.stream.QueueOfferResult.QueueClosed => scala.concurrent.Future.failed[Nothing](CrmClientException.QueueException.QueueClosed) }))(ec)
286 25596 12199 - 12747 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.technical.crm.crmclientcomponenttest loop(maxRetries).flatMap[akka.http.scaladsl.model.ResponseEntity](((x0$1: akka.http.scaladsl.model.HttpResponse) => x0$1 match { case akka.http.scaladsl.model.HttpResponse.unapply(<unapply-selector>) <unapply> ((code @ _), _, (entity @ _), _) if code.isSuccess() => scala.concurrent.Future.successful[akka.http.scaladsl.model.ResponseEntity](entity) case akka.http.scaladsl.model.HttpResponse.unapply(<unapply-selector>) <unapply> ((code @ _), _, (entity @ _), _) => akka.http.scaladsl.unmarshalling.Unmarshal.apply[akka.http.scaladsl.model.ResponseEntity](entity).to[String](akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.stringUnmarshaller, ec, stream.this.Materializer.matFromSystem(DefaultCrmClientComponent.this.actorSystem)).flatMap[Nothing](((response: String) => { val exception: Exception = code match { case akka.http.scaladsl.model.StatusCodes.TooManyRequests => QuotaExceeded.apply(id, response) case (code @ _) => exceptionFn.apply(code, response) }; scala.concurrent.Future.failed[Nothing](exception) }))(ec) }))(ec)