Skip to content

Commit 9054c23

Browse files
committed
Merge branch 'master' of github.com:PolymerLabs/arcs into s2k-schemas
2 parents d15008e + 337b7b2 commit 9054c23

36 files changed

+813
-85
lines changed

java/arcs/android/crdt/ParcelableRawEntity.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ data class ParcelableRawEntity(
3939
parcel.writeTypedObject(ParcelableReferencable(it), flags)
4040
}
4141
}
42+
parcel.writeLong(actual.creationTimestamp)
4243
parcel.writeLong(actual.expirationTimestamp)
4344
}
4445

@@ -67,10 +68,19 @@ data class ParcelableRawEntity(
6768
collections[key] = set
6869
}
6970

71+
@Suppress("GoodTime") // use Instant
72+
val creationTimestamp = requireNotNull(parcel.readLong())
73+
7074
@Suppress("GoodTime") // use Instant
7175
val expirationTimestamp = requireNotNull(parcel.readLong())
7276

73-
val rawEntity = RawEntity(id, singletons, collections, expirationTimestamp)
77+
val rawEntity = RawEntity(
78+
id,
79+
singletons,
80+
collections,
81+
creationTimestamp,
82+
expirationTimestamp
83+
)
7484
return ParcelableRawEntity(rawEntity)
7585
}
7686

java/arcs/core/common/Referencable.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ interface Referencable {
1919
/** Unique identifier of the Referencable object. */
2020
val id: ReferenceId
2121

22+
/** Creation timestamp (in millis) on the Referencable object. */
23+
var creationTimestamp: Long
24+
get() = TODO("not implemented")
25+
set(@Suppress("UNUSED_PARAMETER") value) = TODO("not implemented")
26+
2227
/** Expiration timestamp (in millis) on the Referencable object. */
2328
var expirationTimestamp: Long
2429
get() = TODO("not implemented")

java/arcs/core/data/RawEntity.kt

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,34 @@ data class RawEntity(
2929
override fun unwrap(): Referencable {
3030
val entity = RawEntity(
3131
id = id,
32+
creationTimestamp = creationTimestamp,
3233
expirationTimestamp = expirationTimestamp,
3334
singletons = singletons.mapValues { it.value?.unwrap() },
3435
collections = collections.mapValues {
3536
it.value.map { item -> item.unwrap() }.toSet()
3637
}
3738
)
39+
entity.creationTimestamp = creationTimestamp
3840
entity.expirationTimestamp = expirationTimestamp
3941
return entity
4042
}
4143

44+
/** Entity creation time (in millis). */
45+
@Suppress("GoodTime") // use Instant
46+
override var creationTimestamp: Long = UNINITIALIZED_TIMESTAMP
47+
set(value) {
48+
require(this.creationTimestamp == UNINITIALIZED_TIMESTAMP) {
49+
"cannot override creationTimestamp $value"
50+
}
51+
@Suppress("GoodTime") // use Instant
52+
field = value
53+
}
54+
4255
/** Entity expiration time (in millis). */
4356
@Suppress("GoodTime") // use Instant
44-
override var expirationTimestamp: Long = NO_EXPIRATION
57+
override var expirationTimestamp: Long = UNINITIALIZED_TIMESTAMP
4558
set(value) {
46-
require(this.expirationTimestamp == NO_EXPIRATION) {
59+
require(this.expirationTimestamp == UNINITIALIZED_TIMESTAMP) {
4760
"cannot override expirationTimestamp $value"
4861
}
4962
@Suppress("GoodTime") // use Instant
@@ -62,7 +75,8 @@ data class RawEntity(
6275
id: ReferenceId = NO_REFERENCE_ID,
6376
singletonFields: Set<FieldName> = emptySet(),
6477
collectionFields: Set<FieldName> = emptySet(),
65-
expirationTimestamp: Long = NO_EXPIRATION
78+
creationTimestamp: Long = UNINITIALIZED_TIMESTAMP,
79+
expirationTimestamp: Long = UNINITIALIZED_TIMESTAMP
6680
) : this(
6781
id,
6882
singletonFields.associateWith { null },
@@ -73,17 +87,21 @@ data class RawEntity(
7387

7488
companion object {
7589
const val NO_REFERENCE_ID = "NO REFERENCE ID"
76-
const val NO_EXPIRATION: Long = -1
90+
const val UNINITIALIZED_TIMESTAMP: Long = -1
7791
}
7892
}
7993

8094
fun RawEntity(
8195
id: String,
8296
singletons: Map<FieldName, Referencable?>,
8397
collections: Map<FieldName, Set<Referencable>>,
98+
creationTimestamp: Long,
8499
expirationTimestamp: Long
85100
) = RawEntity(
86101
id,
87102
singletons,
88103
collections
89-
).also { it.expirationTimestamp = expirationTimestamp }
104+
).also {
105+
it.creationTimestamp = creationTimestamp
106+
it.expirationTimestamp = expirationTimestamp
107+
}

java/arcs/core/data/Ttl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ sealed class Ttl(count: Int, val isInfinite: Boolean = false) {
3434
override fun hashCode(): Int = minutes.hashCode()
3535

3636
fun calculateExpiration(time: Time): Long =
37-
if (isInfinite) RawEntity.NO_EXPIRATION
37+
if (isInfinite) RawEntity.UNINITIALIZED_TIMESTAMP
3838
else requireNotNull(time).currentTimeMillis + (minutes * 60 * 1000)
3939

4040
data class Minutes(val count: Int) : Ttl(count)

java/arcs/core/data/testdata/BUILD

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
load(
22
"//third_party/java/arcs/build_defs:build_defs.bzl",
3+
"arcs_kt_plan",
34
"arcs_manifest_proto",
45
)
56

@@ -19,3 +20,9 @@ arcs_manifest_proto(
1920
src = "Example.arcs",
2021
visibility = ["//visibility:public"],
2122
)
23+
24+
arcs_kt_plan(
25+
name = "example_plan",
26+
src = "Example.arcs",
27+
visibility = ["//visibility:public"],
28+
)

java/arcs/core/storage/handle/CollectionImpl.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class CollectionImpl<T : Referencable>(
8888
*/
8989
suspend fun store(entity: T): Boolean {
9090
log.debug { "Storing: $entity" }
91+
@Suppress("GoodTime") // use Instant
92+
entity.creationTimestamp = requireNotNull(time).currentTimeMillis
9193
if (!Ttl.Infinite.equals(ttl)) {
9294
@Suppress("GoodTime") // use Instant
9395
entity.expirationTimestamp = ttl.calculateExpiration(time)

java/arcs/core/storage/handle/SingletonImpl.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class SingletonImpl<T : Referencable>(
6464
* did not apply fully. Fetch the latest value and retry.
6565
* */
6666
suspend fun store(entity: T): Boolean {
67+
@Suppress("GoodTime") // use Instant
68+
entity.creationTimestamp = requireNotNull(time).currentTimeMillis
6769
if (!Ttl.Infinite.equals(ttl)) {
6870
@Suppress("GoodTime") // use Instant
6971
entity.expirationTimestamp = ttl.calculateExpiration(time)

java/arcs/sdk/android/dev/api/CollectionProxy.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,15 @@ public Referencable unwrap() {
286286
return this;
287287
}
288288

289+
@Override
290+
public long getCreationTimestamp() {
291+
throw new AssertionError("ModelEntry::getCreationTimestamp not implemented");
292+
}
293+
294+
@Override
295+
public void setCreationTimestamp(long creationTimestamp) {
296+
throw new AssertionError("ModelEntry::setCreationTimestamp not implemented");
297+
}
289298

290299
@Override
291300
public long getExpirationTimestamp() {

java/arcs/sdk/android/storage/ServiceStore.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,15 @@ class ServiceStore<Data : CrdtData, Op : CrdtOperation, ConsumerData>(
142142
val service = connection.connectAsync().await()
143143

144144
val messageChannel = ParcelableProxyMessageChannel(coroutineContext)
145-
serviceCallbackToken = withContext(coroutineContext) {
146-
service.registerCallback(messageChannel)
147-
}
148145

146+
// Open subscription before attaching callback to make sure that we capture all messages
147+
val subscription = messageChannel.openSubscription()
149148
scope.launch {
150-
messageChannel.openSubscription().consumeEach { handleMessageAndResultFromService(it) }
149+
subscription.consumeEach { handleMessageAndResultFromService(it) }
150+
}
151+
152+
serviceCallbackToken = withContext(coroutineContext) {
153+
service.registerCallback(messageChannel)
151154
}
152155

153156
this.serviceConnection = connection

javatests/arcs/android/host/BUILD

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,18 @@ arcs_kt_android_test_suite(
1717
deps = [
1818
":schemas",
1919
":services",
20-
"//java/arcs/android/crdt",
2120
"//java/arcs/android/host",
2221
"//java/arcs/android/sdk/host",
23-
"//java/arcs/android/storage",
2422
"//java/arcs/android/storage/database",
2523
"//java/arcs/android/storage/handle",
26-
"//java/arcs/android/storage/service",
27-
"//java/arcs/android/storage/service:aidl",
28-
"//java/arcs/core/allocator",
2924
"//java/arcs/core/common",
30-
"//java/arcs/core/crdt",
3125
"//java/arcs/core/data",
3226
"//java/arcs/core/host",
3327
"//java/arcs/core/storage",
34-
"//java/arcs/core/storage:storage_key",
3528
"//java/arcs/core/storage/api",
3629
"//java/arcs/core/storage/driver",
37-
"//java/arcs/core/storage/handle",
3830
"//java/arcs/core/storage/referencemode",
3931
"//java/arcs/core/testutil",
40-
"//java/arcs/core/type",
4132
"//java/arcs/core/util",
4233
"//java/arcs/sdk/android/storage",
4334
"//java/arcs/sdk/android/storage/service",
@@ -55,7 +46,6 @@ arcs_kt_android_test_suite(
5546
"//third_party/kotlin/kotlin:kotlin_reflect",
5647
"//third_party/kotlin/kotlinx_coroutines",
5748
"//third_party/kotlin/kotlinx_coroutines:kotlinx_coroutines_test",
58-
"//third_party/kotlin/mockito_kotlin:mockito_kotlin-android",
5949
],
6050
)
6151

javatests/arcs/android/storage/database/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package(default_visibility = ["//visibility:public"])
99

1010
arcs_kt_android_test_suite(
1111
name = "database",
12+
size = "medium",
1213
manifest = "//java/arcs/android/common:AndroidManifest.xml",
1314
package = "arcs.android.storage.database",
1415
deps = [

javatests/arcs/core/storage/handle/CollectionIntegrationTest.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,25 @@ class CollectionIntegrationTest {
170170
fun addElementsWithTtls() = runBlockingTest {
171171
val person = Person("John", 29, false)
172172
collectionA.store(person.toRawEntity())
173+
val creationTimestampA = collectionA.fetchAll().first().creationTimestamp
174+
assertThat(creationTimestampA).isNotEqualTo(RawEntity.UNINITIALIZED_TIMESTAMP)
173175
assertThat(collectionA.fetchAll().first().expirationTimestamp)
174-
.isEqualTo(RawEntity.NO_EXPIRATION)
176+
.isEqualTo(RawEntity.UNINITIALIZED_TIMESTAMP)
175177

176178
val collectionC = CollectionImpl("collectionC", storageProxy, null, null, Ttl.Days(2), TimeImpl())
177179
storageProxy.registerHandle(collectionC)
178180
assertThat(collectionC.store(person.toRawEntity())).isTrue()
179181
val entityC = collectionC.fetchAll().first()
180-
assertThat(entityC.expirationTimestamp).isGreaterThan(RawEntity.NO_EXPIRATION)
182+
assertThat(entityC.creationTimestamp).isGreaterThan(creationTimestampA)
183+
assertThat(entityC.expirationTimestamp).isGreaterThan(RawEntity.UNINITIALIZED_TIMESTAMP)
181184

182185
val collectionD = CollectionImpl("collectionD", storageProxy, null, null, Ttl.Minutes(1), TimeImpl())
183186
storageProxy.registerHandle(collectionD)
184187
assertThat(collectionD.store(person.toRawEntity())).isTrue()
185188
val entityD = collectionD.fetchAll().first()
186-
assertThat(entityD.expirationTimestamp).isGreaterThan(RawEntity.NO_EXPIRATION)
189+
assertThat(entityD.creationTimestamp).isGreaterThan(creationTimestampA)
190+
assertThat(entityD.creationTimestamp).isGreaterThan(entityC.creationTimestamp)
191+
assertThat(entityD.expirationTimestamp).isGreaterThan(RawEntity.UNINITIALIZED_TIMESTAMP)
187192
assertThat(entityC.expirationTimestamp).isGreaterThan(entityD.expirationTimestamp)
188193
}
189194

javatests/arcs/core/storage/handle/SingletonIntegrationTest.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,20 +138,25 @@ class SingletonIntegrationTest {
138138
fun addEntityWithTtl() = runBlockingTest {
139139
val person = Person("Jane", 29, false)
140140
assertThat(singletonA.store(person.toRawEntity())).isTrue()
141+
val creationTimestampA = requireNotNull(singletonA.fetch()).creationTimestamp;
142+
assertThat(creationTimestampA).isNotEqualTo(RawEntity.UNINITIALIZED_TIMESTAMP)
141143
assertThat(requireNotNull(singletonA.fetch()).expirationTimestamp)
142-
.isEqualTo(RawEntity.NO_EXPIRATION)
144+
.isEqualTo(RawEntity.UNINITIALIZED_TIMESTAMP)
143145

144146
val singletonC = SingletonImpl("singletonC", storageProxy, null, Ttl.Days(2), TimeImpl())
145147
storageProxy.registerHandle(singletonC)
146148
assertThat(singletonC.store(person.toRawEntity())).isTrue()
147149
val entityC = requireNotNull(singletonC.fetch())
148-
assertThat(entityC.expirationTimestamp).isGreaterThan(RawEntity.NO_EXPIRATION)
150+
assertThat(entityC.creationTimestamp).isGreaterThan(creationTimestampA)
151+
assertThat(entityC.expirationTimestamp).isGreaterThan(RawEntity.UNINITIALIZED_TIMESTAMP)
149152

150153
val singletonD = SingletonImpl("singletonD", storageProxy, null, Ttl.Minutes(1), TimeImpl())
151154
storageProxy.registerHandle(singletonD)
152155
assertThat(singletonD.store(person.toRawEntity())).isTrue()
153156
val entityD = requireNotNull(singletonD.fetch())
154-
assertThat(entityD.expirationTimestamp).isGreaterThan(RawEntity.NO_EXPIRATION)
157+
assertThat(entityD.creationTimestamp).isGreaterThan(creationTimestampA)
158+
assertThat(entityD.creationTimestamp).isGreaterThan(entityC.creationTimestamp)
159+
assertThat(entityD.expirationTimestamp).isGreaterThan(RawEntity.UNINITIALIZED_TIMESTAMP)
155160
assertThat(entityC.expirationTimestamp).isGreaterThan(entityD.expirationTimestamp)
156161
}
157162

src/runtime/capabilities.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class Capabilities {
1818
}
1919

2020
get isPersistent() { return this.capabilities.has('persistent'); }
21+
get isQueryable() { return this.capabilities.has('queryable'); }
2122
get isTiedToRuntime() { return this.capabilities.has('tied-to-runtime'); }
2223
get isTiedToArc() { return this.capabilities.has('tied-to-arc'); }
2324

@@ -44,4 +45,6 @@ export class Capabilities {
4445
static readonly tiedToArc = new Capabilities(['tied-to-arc']);
4546
static readonly tiedToRuntime = new Capabilities(['tied-to-runtime']);
4647
static readonly persistent = new Capabilities(['persistent']);
48+
static readonly queryable = new Capabilities(['queryable']);
49+
static readonly persistentQueryable = new Capabilities(['persistent', 'queryable']);
4750
}

src/runtime/manifest-ast-nodes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ export interface ParticleConnectionTargetComponents extends BaseNode {
402402

403403
export type RecipeHandleFate = string;
404404

405-
export type RecipeHandleCapability = 'persistent' | 'tied-to-runtime' | 'tied-to-arc';
405+
export type RecipeHandleCapability = 'persistent' | 'queryable' | 'tied-to-runtime' | 'tied-to-arc';
406406

407407
export interface RecipeHandle extends BaseNode {
408408
kind: 'handle';

src/runtime/manifest-parser.pegjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ RecipeHandleFate
10641064

10651065
RecipeHandleCapability
10661066
= 'persistent'
1067+
/ 'queryable'
10671068
/ 'tied-to-runtime'
10681069
/ 'tied-to-arc'
10691070

0 commit comments

Comments
 (0)