Skip to content

Commit

Permalink
Handle exceptions raised by the Executor during initialization of the…
Browse files Browse the repository at this point in the history
… thread pool for emitter (close #694)
  • Loading branch information
matus-tomlein committed Aug 21, 2024
1 parent fa694a5 commit 91b2779
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2015-present Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
package com.snowplowanalytics.snowplow.event

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.snowplowanalytics.core.constants.Parameters
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*

@RunWith(AndroidJUnit4::class)
class ScreenViewTest {
@Test
fun testExpectedForm() {
var screenView = ScreenView("name")
var data: Map<String, Any?> = screenView.dataPayload
Assert.assertNotNull(data)
Assert.assertEquals("name", data[Parameters.SV_NAME])
Assert.assertTrue(data.containsKey(Parameters.SV_ID))
val id = UUID.randomUUID()
screenView = ScreenView("name", id)
data = screenView.dataPayload
Assert.assertNotNull(data)
Assert.assertEquals(id.toString(), data[Parameters.SV_ID])
Assert.assertEquals("name", data[Parameters.SV_NAME])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class EventStoreTest {
@Throws(InterruptedException::class)
fun testInsertPayload() {
val eventStore = eventStore()
val id = eventStore.insertEvent(payload())
val id = eventStore.insertEvent(payload())!!
val lastRowId = eventStore.lastInsertedRowId
val event = eventStore.getEvent(id)
Assert.assertEquals(id, lastRowId)
Expand Down Expand Up @@ -153,7 +153,7 @@ class EventStoreTest {
@Throws(InterruptedException::class)
fun testRemoveIndividualEvent() {
val eventStore = eventStore()
val id = eventStore.insertEvent(payload())
val id = eventStore.insertEvent(payload())!!
var res = eventStore.removeEvent(id)
Assert.assertEquals(0, eventStore.size())
Assert.assertTrue(res)
Expand All @@ -169,9 +169,9 @@ class EventStoreTest {
fun testRemoveRangeOfEvents() {
val eventStore = eventStore()
val idList: MutableList<Long> = ArrayList()
idList.add(eventStore.insertEvent(payload()))
idList.add(eventStore.insertEvent(payload()))
idList.add(eventStore.insertEvent(payload()))
idList.add(eventStore.insertEvent(payload())!!)
idList.add(eventStore.insertEvent(payload())!!)
idList.add(eventStore.insertEvent(payload())!!)
Assert.assertEquals(3, idList.size.toLong())
Assert.assertEquals(3, eventStore.size())
var res = eventStore.removeEvents(idList)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ package com.snowplowanalytics.core.emitter

import androidx.annotation.RestrictTo
import com.snowplowanalytics.core.tracker.Logger
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.Future
import java.util.concurrent.*

/**
* Static Class which holds the logic for controlling
Expand Down Expand Up @@ -51,11 +48,15 @@ object Executor {
*/
@Synchronized
@JvmStatic
private fun getExecutor(): ExecutorService {
private fun getExecutor(): ExecutorService? {
if (executor == null) {
executor = Executors.newScheduledThreadPool(threadCount)
try {
executor = Executors.newScheduledThreadPool(threadCount)
} catch (e: Exception) {
Logger.e("Executor", e.message ?: "Failed to create thread pool")
}
}
return executor!!
return executor
}

/**
Expand Down Expand Up @@ -105,7 +106,7 @@ object Executor {
fun execute(runnable: Runnable?, exceptionHandler: ExceptionHandler?) {
val executor = getExecutor()
try {
executor.execute {
executor?.execute {
try {
runnable?.run()
} catch (t: Throwable) {
Expand All @@ -125,8 +126,13 @@ object Executor {
* @return the future object to be queried
*/
@JvmStatic
fun futureCallable(callable: Callable<*>): Future<*> {
return getExecutor().submit(callable)
fun futureCallable(callable: Callable<*>): Future<*>? {
return try {
getExecutor()?.submit(callable)
} catch (e: Exception) {
Logger.e("Executor", e.message ?: "Failed to submit task")
null
}
}

/**
Expand All @@ -136,7 +142,11 @@ object Executor {
@JvmStatic
fun shutdown(): ExecutorService? {
if (executor != null) {
executor!!.shutdown()
try {
executor?.shutdown()
} catch (e: Exception) {
Logger.e("Executor", e.message ?: "Failed to shutdown")
}
val es = executor
executor = null
return es
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import kotlin.time.Duration
class SQLiteEventStore(context: Context, private val namespace: String) : EventStore {
private val payloadWaitingList: MutableList<Payload> = ArrayList()
private var database: SQLiteDatabase? = null
private lateinit var dbHelper: EventStoreHelper
private var dbHelper: EventStoreHelper? = null
private val allColumns = arrayOf(
EventStoreHelper.COLUMN_ID,
EventStoreHelper.COLUMN_EVENT_DATA,
Expand All @@ -62,7 +62,7 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
* @return a boolean for database status
*/
val databaseOpen: Boolean
get() = database != null && database!!.isOpen
get() = database != null && database?.isOpen ?: false

/**
* Creates a new Event Store
Expand Down Expand Up @@ -91,7 +91,7 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
*/
fun open() {
if (!databaseOpen) {
database = dbHelper.writableDatabase
database = dbHelper?.writableDatabase
database?.enableWriteAheadLogging()
}
}
Expand All @@ -100,7 +100,7 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
* Closes the database
*/
fun close() {
dbHelper.close()
dbHelper?.close()
EventStoreHelper.removeInstance(namespace)
}

Expand All @@ -112,25 +112,27 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
* @return a boolean stating if the insert
* was a success or not
*/
fun insertEvent(payload: Payload): Long {
fun insertEvent(payload: Payload): Long? {
if (databaseOpen) {
val database = database ?: return null
val bytes = Util.serialize(Util.objectMapToString(payload.map))
val values = ContentValues(2)
values.put(EventStoreHelper.COLUMN_EVENT_DATA, bytes)
lastInsertedRowId =
database!!.insert(EventStoreHelper.TABLE_EVENTS, null, values)
database.insert(EventStoreHelper.TABLE_EVENTS, null, values)
Logger.d(TAG, "Added event to database: %s", lastInsertedRowId)
return lastInsertedRowId
}
Logger.d(TAG, "Added event to database: %s", lastInsertedRowId)
return lastInsertedRowId
return null
}

override fun removeEvent(id: Long): Boolean {
var retval = -1
if (databaseOpen) {
retval = database!!.delete(
retval = database?.delete(
EventStoreHelper.TABLE_EVENTS,
EventStoreHelper.COLUMN_ID + "=" + id, null
)
) ?: retval
}
Logger.d(TAG, "Removed event from database: %s", "" + id)
return retval == 1
Expand All @@ -142,10 +144,10 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
}
var retval = -1
if (databaseOpen) {
retval = database!!.delete(
retval = database?.delete(
EventStoreHelper.TABLE_EVENTS,
EventStoreHelper.COLUMN_ID + " in (" + Util.joinLongList(ids) + ")", null
)
) ?: retval
}
Logger.d(TAG, "Removed events from database: %s", retval)
return retval == ids.size
Expand All @@ -155,7 +157,7 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
var retval = 0
Logger.d(TAG, "Removing all events from database.")
if (databaseOpen) {
retval = database!!.delete(EventStoreHelper.TABLE_EVENTS, null, null)
retval = database?.delete(EventStoreHelper.TABLE_EVENTS, null, null) ?: retval
} else {
Logger.e(TAG, "Database is not open.")
}
Expand Down Expand Up @@ -196,9 +198,10 @@ class SQLiteEventStore(context: Context, private val namespace: String) : EventS
private fun queryDatabase(query: String?, orderBy: String?): List<Map<String, Any?>> {
val res: MutableList<Map<String, Any?>> = ArrayList()
if (databaseOpen) {
val database = database ?: return res
var cursor: Cursor? = null
try {
cursor = database!!.query(
cursor = database.query(
EventStoreHelper.TABLE_EVENTS,
allColumns,
query,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ class OkHttpNetworkConnection private constructor(builder: OkHttpNetworkConnecti
request,
userAgent
) else buildPostRequest(request, userAgent)
futures.add(Executor.futureCallable(getRequestCallable(okHttpRequest)))
Executor.futureCallable(getRequestCallable(okHttpRequest))?.let { futures.add(it) }
}
Logger.d(TAG, "Request Futures: %s", futures.size)

Expand Down

0 comments on commit 91b2779

Please sign in to comment.