Skip to content

Commit f2d3d8e

Browse files
committed
add more comments
1 parent 136f536 commit f2d3d8e

File tree

8 files changed

+195
-53
lines changed

8 files changed

+195
-53
lines changed

android/src/test/java/com/segment/analytics/kotlin/android/StorageTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class StorageTests {
7474
"123",
7575
UnconfinedTestDispatcher()
7676
)
77-
androidStorage.subscribeToStore()
77+
androidStorage.initialize()
7878
}
7979

8080

core/src/main/java/com/segment/analytics/kotlin/core/Analytics.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ open class Analytics protected constructor(
128128
it.provide(System.defaultState(configuration, storage))
129129

130130
// subscribe to store after state is provided
131-
storage.subscribeToStore()
131+
storage.initialize()
132132
Telemetry.subscribe(store)
133133
}
134134

core/src/main/java/com/segment/analytics/kotlin/core/Storage.kt

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,16 @@ import kotlinx.coroutines.CoroutineDispatcher
44
import kotlinx.serialization.json.Json
55
import kotlinx.serialization.json.JsonObject
66
import sovran.kotlin.Store
7-
import java.io.File
87
import java.io.InputStream
98

109
/**
11-
* Storage interface that abstracts storage of
12-
* - user data
13-
* - segment settings
14-
* - segment events
15-
* - other configs
16-
*
17-
* Constraints:
18-
* - Segment Events must be stored on a file, following the batch format
19-
* - all storage is in terms of String (to make API simple)
20-
* - storage is restricted to keys declared in `Storage.Constants`
10+
* The protocol of how events are read and stored.
11+
* Implement this interface if you wanna your events
12+
* to be read and stored in the way you want (for
13+
* example: from/to remote server, from/to local database
14+
* from/to encrypted source).
15+
* By default, we have implemented read and store events
16+
* from/to memory and file storage.
2117
*/
2218
interface Storage {
2319
companion object {
@@ -45,45 +41,64 @@ interface Storage {
4541
DeviceId("segment.device.id")
4642
}
4743

48-
suspend fun subscribeToStore()
44+
/**
45+
* Initialization of the storage.
46+
* All prerequisite setups should be done in this method.
47+
*/
48+
suspend fun initialize()
49+
50+
/**
51+
* Write a value of the Storage.Constants type to storage
52+
*
53+
* @param key The type of the value
54+
* @param value Value
55+
*/
4956
suspend fun write(key: Constants, value: String)
57+
58+
/**
59+
* Write a key/value pair to prefs
60+
*
61+
* @param key Key
62+
* @param value Value
63+
*/
5064
fun writePrefs(key: Constants, value: String)
65+
66+
/**
67+
* Read the value of a given type
68+
*
69+
* @param key The type of the value
70+
* @return value of the given type
71+
*/
5172
fun read(key: Constants): String?
73+
74+
/**
75+
* Read the given source stream as an InputStream
76+
*
77+
* @param source stream to read
78+
* @return result as InputStream
79+
*/
5280
fun readAsStream(source: String): InputStream?
81+
82+
/**
83+
* Remove the data of a given type
84+
*
85+
* @param key type of the data to remove
86+
* @return status of the operation
87+
*/
5388
fun remove(key: Constants): Boolean
89+
90+
/**
91+
* Remove a stream
92+
*
93+
* @param filePath the fullname/identifier of a stream
94+
* @return status of the operation
95+
*/
5496
fun removeFile(filePath: String): Boolean
5597

5698
/**
57-
* Direct writes to a new file, and close the current file.
58-
* This function is useful in cases such as `flush`, that
59-
* we want to finish writing the current file, and have it
60-
* flushed to server.
99+
* Close and finish the current stream and start a new one
61100
*/
62101
suspend fun rollover()
63-
64-
suspend fun userInfoUpdate(userInfo: UserInfo) {
65-
write(Constants.AnonymousId, userInfo.anonymousId)
66-
67-
userInfo.userId?.let {
68-
write(Constants.UserId, it)
69-
} ?: run {
70-
remove(Constants.UserId)
71-
}
72-
73-
userInfo.traits?.let {
74-
write(Constants.Traits, Json.encodeToString(JsonObject.serializer(), it))
75-
} ?: run {
76-
remove(Constants.Traits)
77-
}
78-
}
79-
80-
suspend fun systemUpdate(system: System) {
81-
system.settings?.let {
82-
write(Constants.Settings, Json.encodeToString(Settings.serializer(), it))
83-
} ?: run {
84-
remove(Constants.Settings)
85-
}
86-
}
87102
}
88103

89104
fun parseFilePaths(filePathStr: String?): List<String> {

core/src/main/java/com/segment/analytics/kotlin/core/utilities/EventStream.kt

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,81 @@ import java.io.InputStream
77
import java.lang.StringBuilder
88
import java.util.concurrent.ConcurrentHashMap
99

10+
/**
11+
* The protocol of how events are read and stored.
12+
* Implement this interface if you wanna your events
13+
* to be read and stored in the way you want (for
14+
* example: from/to remote server, from/to local database
15+
* from/to encrypted source).
16+
* By default, we have implemented read and store events
17+
* from/to memory and file storage.
18+
*
19+
* A stream is defined as something that contains a batch of
20+
* events. It can be in the form of any of the following:
21+
* * a file
22+
* * an in-memory entry
23+
* * a table entry in database
24+
*/
1025
interface EventStream {
26+
/**
27+
* Length of current stream
28+
*/
1129
val length: Long
1230

31+
/**
32+
* Check if a stream is opened
33+
*/
1334
val isOpened: Boolean
1435

1536
/**
16-
* open or create a file
17-
* @param file name of file
18-
* @return true if a new file is created
37+
* Open the stream with the given name. Creates a new one if not already exists.
38+
*
39+
* @param file name of the stream
40+
* @return true if a new stream is created
1941
*/
2042
fun openOrCreate(file: String): Boolean
2143

44+
/**
45+
* Append content to the opening stream
46+
*
47+
* @param content Content to append
48+
*/
2249
fun write(content: String)
2350

2451
/**
25-
* read the list of files in directory
26-
* @return a list of file names in directory
52+
* Read the list of streams in directory
53+
* @return a list of stream names in directory
2754
*/
2855
fun read(): List<String>
2956

57+
/**
58+
* Remove the stream with the given name
59+
*
60+
* @param file name of stream to be removed
61+
*/
3062
fun remove(file: String)
3163

64+
/**
65+
* Close the current opening stream without finish it,
66+
* so that the stream can be opened for future appends.
67+
*/
3268
fun close()
3369

70+
/**
71+
* Close and finish the current opening stream.
72+
* Pass a withRename closure if you want to distinguish completed
73+
* streams from ongoing stream
74+
*
75+
* @param withRename a callback that renames a finished stream
76+
*/
3477
fun finishAndClose(withRename: ((name: String) -> String)? = null)
3578

79+
/**
80+
* Read the stream with the given name as an InputStream.
81+
* Needed for HTTPClient to upload data
82+
*
83+
* @param source the full name of a stream
84+
*/
3685
fun readAsStream(source: String): InputStream?
3786
}
3887

@@ -81,16 +130,14 @@ class InMemoryEventStream: EventStream {
81130
}
82131

83132
override fun finishAndClose(withRename: ((name: String) -> String)?) {
84-
currFile ?: return
85-
86133
currFile?.let {
87134
withRename?.let { rename ->
88135
directory.remove(it.name)
89136
directory[rename(it.name)] = it
90137
}
138+
currFile = null
91139
}
92140

93-
currFile = null
94141
}
95142

96143
override fun readAsStream(source: String): InputStream? = directory[source]?.toStream()
@@ -158,6 +205,13 @@ class FileEventStream(
158205

159206
override fun read(): List<String> = (directory.listFiles() ?: emptyArray()).map { it.absolutePath }
160207

208+
/**
209+
* Remove the given file from disk
210+
*
211+
* NOTE: file string has to be the full path of the file
212+
*
213+
* @param file full path of the file to be deleted
214+
*/
161215
override fun remove(file: String) {
162216
File(file).delete()
163217
}

core/src/main/java/com/segment/analytics/kotlin/core/utilities/KVS.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,52 @@ interface KVS {
1212
@Deprecated("Deprecated in favor of `put`", ReplaceWith("put(key, value)"))
1313
fun putInt(key: String, value: Int): Boolean = put(key, value)
1414

15+
/**
16+
* Read the value of a given key as integer
17+
* @param key Key
18+
* @param defaultVal Fallback value to use
19+
* @return Value
20+
*/
1521
fun get(key: String, defaultVal: Int): Int
22+
23+
/**
24+
* Store the key value pair
25+
* @param key Key
26+
* @param value Fallback value to use
27+
* @return Status of the operation
28+
*/
1629
fun put(key: String, value: Int): Boolean
30+
31+
/**
32+
* Read the value of a given key as integer
33+
* @param key Key
34+
* @param defaultVal Fallback value to use
35+
* @return Value
36+
*/
1737
fun get(key: String, defaultVal: String?): String?
38+
39+
/**
40+
* Store the key value pair
41+
* @param key Key
42+
* @param value Fallback value to use
43+
* @return Status of the operation
44+
*/
1845
fun put(key: String, value: String): Boolean
46+
47+
/**
48+
* Remove a key/value pair by key
49+
*
50+
* @param key Key
51+
* @return Status of the operation
52+
*/
1953
fun remove(key: String): Boolean
54+
55+
/**
56+
* checks if a given key exists
57+
*
58+
* @param Key
59+
* @return Status of the operation
60+
*/
2061
fun contains(key: String): Boolean
2162
}
2263

core/src/main/java/com/segment/analytics/kotlin/core/utilities/StorageImpl.kt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.segment.analytics.kotlin.core.utilities
22

33
import com.segment.analytics.kotlin.core.Analytics
4+
import com.segment.analytics.kotlin.core.Settings
45
import com.segment.analytics.kotlin.core.Storage
56
import com.segment.analytics.kotlin.core.Storage.Companion.MAX_FILE_SIZE
67
import com.segment.analytics.kotlin.core.Storage.Companion.MAX_PAYLOAD_SIZE
@@ -10,6 +11,8 @@ import com.segment.analytics.kotlin.core.UserInfo
1011
import com.segment.analytics.kotlin.core.reportInternalError
1112
import kotlinx.coroutines.CoroutineDispatcher
1213
import kotlinx.coroutines.sync.Semaphore
14+
import kotlinx.serialization.json.Json
15+
import kotlinx.serialization.json.JsonObject
1316
import sovran.kotlin.Store
1417
import sovran.kotlin.Subscriber
1518
import java.io.File
@@ -41,7 +44,7 @@ open class StorageImpl(
4144
private val currentFile
4245
get() = "$writeKey-${propertiesFile.get(fileIndexKey, 0)}.$ext"
4346

44-
override suspend fun subscribeToStore() {
47+
override suspend fun initialize() {
4548
store.subscribe(
4649
this,
4750
UserInfo::class,
@@ -58,6 +61,30 @@ open class StorageImpl(
5861
)
5962
}
6063

64+
suspend fun userInfoUpdate(userInfo: UserInfo) {
65+
write(Storage.Constants.AnonymousId, userInfo.anonymousId)
66+
67+
userInfo.userId?.let {
68+
write(Storage.Constants.UserId, it)
69+
} ?: run {
70+
remove(Storage.Constants.UserId)
71+
}
72+
73+
userInfo.traits?.let {
74+
write(Storage.Constants.Traits, Json.encodeToString(JsonObject.serializer(), it))
75+
} ?: run {
76+
remove(Storage.Constants.Traits)
77+
}
78+
}
79+
80+
suspend fun systemUpdate(system: System) {
81+
system.settings?.let {
82+
write(Storage.Constants.Settings, Json.encodeToString(Settings.serializer(), it))
83+
} ?: run {
84+
remove(Storage.Constants.Settings)
85+
}
86+
}
87+
6188
override suspend fun write(key: Storage.Constants, value: String) {
6289
when (key) {
6390
Storage.Constants.Events -> {

core/src/test/kotlin/com/segment/analytics/kotlin/core/utilities/EventStreamTest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class EventStreamTest {
177177
fun openOrCreateTest() {
178178
var actual = eventStream.openOrCreate("test.tmp")
179179
assertTrue(actual)
180+
assertTrue(File(dir, "test.tmp").exists())
180181

181182
actual = eventStream.openOrCreate("test.tmp")
182183
assertFalse(actual)
@@ -234,7 +235,11 @@ class EventStreamTest {
234235
eventStream.finishAndClose {
235236
removeFileExtension(it)
236237
}
237-
eventStream.remove("test")
238+
assertTrue(File(dir, "test").exists())
239+
240+
eventStream.remove(File(dir, "test").absolutePath)
241+
assertFalse(File(dir, "test").exists())
242+
238243
val newFile = eventStream.openOrCreate("test.tmp")
239244

240245
assertTrue(newFile)

core/src/test/kotlin/com/segment/analytics/kotlin/core/utilities/StorageImplTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ internal class StorageImplTest {
7575
}
7676
}
7777
storage = storageProvider.createStorage() as StorageImpl
78-
storage.subscribeToStore()
78+
storage.initialize()
7979
}
8080

8181

0 commit comments

Comments
 (0)