|
15 | 15 | import com.google.common.util.concurrent.MoreExecutors; |
16 | 16 | import java.util.Map; |
17 | 17 | import java.util.Properties; |
| 18 | +import java.util.concurrent.ExecutorService; |
| 19 | +import java.util.concurrent.TimeUnit; |
18 | 20 | import org.apache.http.HttpHeaders; |
19 | 21 | import org.apache.http.StatusLine; |
20 | 22 | import org.apache.http.client.methods.CloseableHttpResponse; |
@@ -139,4 +141,114 @@ public void testExportEventDoesNotThrowErrorsInFailures() throws Exception { |
139 | 141 | () -> client.exportEvent(new TelemetryFrontendLog().setFrontendLogEventId("event2"))); |
140 | 142 | } |
141 | 143 | } |
| 144 | + |
| 145 | + @Test |
| 146 | + public void testPeriodicFlushWithAuthenticatedClient() throws Exception { |
| 147 | + try (MockedStatic<DatabricksHttpClientFactory> factoryMocked = |
| 148 | + mockStatic(DatabricksHttpClientFactory.class)) { |
| 149 | + DatabricksHttpClientFactory mockFactory = mock(DatabricksHttpClientFactory.class); |
| 150 | + factoryMocked.when(DatabricksHttpClientFactory::getInstance).thenReturn(mockFactory); |
| 151 | + when(mockFactory.getClient(any())).thenReturn(mockHttpClient); |
| 152 | + when(mockHttpClient.execute(any())).thenReturn(mockHttpResponse); |
| 153 | + when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine); |
| 154 | + when(mockStatusLine.getStatusCode()).thenReturn(200); |
| 155 | + TelemetryResponse response = new TelemetryResponse().setNumSuccess(1L).setNumProtoSuccess(1L); |
| 156 | + when(mockHttpResponse.getEntity()) |
| 157 | + .thenReturn(new StringEntity(new ObjectMapper().writeValueAsString(response))); |
| 158 | + |
| 159 | + Map<String, String> headers = Map.of(HttpHeaders.AUTHORIZATION, "token"); |
| 160 | + when(databricksConfig.authenticate()).thenReturn(headers); |
| 161 | + |
| 162 | + // JDBC URL with 2 seconds flush interval |
| 163 | + String jdbcUrlWith2SecondsFlush = |
| 164 | + "jdbc:databricks://adb-20.azuredatabricks.net:4423/default;transportMode=http;ssl=1;AuthMech=3;httpPath=/sql/1.0/warehouses/ghgjhgj;UserAgentEntry=MyApp;EnableTelemetry=1;TelemetryBatchSize=2;TelemetryFlushInterval=2000"; |
| 165 | + |
| 166 | + IDatabricksConnectionContext context = |
| 167 | + DatabricksConnectionContext.parse(jdbcUrlWith2SecondsFlush, new Properties()); |
| 168 | + TelemetryClient client = |
| 169 | + new TelemetryClient(context, MoreExecutors.newDirectExecutorService(), databricksConfig); |
| 170 | + |
| 171 | + // Add a single event that won't trigger batch flush |
| 172 | + client.exportEvent(new TelemetryFrontendLog().setFrontendLogEventId("event1")); |
| 173 | + assertEquals(1, client.getCurrentSize()); |
| 174 | + |
| 175 | + // Wait for a short time to verify the periodic flush doesn't trigger immediately |
| 176 | + Thread.sleep(100); |
| 177 | + assertEquals(1, client.getCurrentSize()); |
| 178 | + |
| 179 | + // Wait for 2 seconds to trigger the periodic flush |
| 180 | + Thread.sleep(2000); |
| 181 | + assertEquals(0, client.getCurrentSize()); |
| 182 | + |
| 183 | + client.exportEvent(new TelemetryFrontendLog().setFrontendLogEventId("event2")); |
| 184 | + assertEquals(1, client.getCurrentSize()); |
| 185 | + // Close the client to trigger final flush |
| 186 | + client.close(); |
| 187 | + assertEquals(0, client.getCurrentSize()); |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + @Test |
| 192 | + public void testTimerResetOnBatchSizeFlush() throws Exception { |
| 193 | + TelemetryClient client = null; |
| 194 | + ExecutorService executor = null; |
| 195 | + try (MockedStatic<DatabricksHttpClientFactory> factoryMocked = |
| 196 | + mockStatic(DatabricksHttpClientFactory.class)) { |
| 197 | + DatabricksHttpClientFactory mockFactory = mock(DatabricksHttpClientFactory.class); |
| 198 | + factoryMocked.when(DatabricksHttpClientFactory::getInstance).thenReturn(mockFactory); |
| 199 | + when(mockFactory.getClient(any())).thenReturn(mockHttpClient); |
| 200 | + when(mockHttpClient.execute(any())).thenReturn(mockHttpResponse); |
| 201 | + when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine); |
| 202 | + when(mockStatusLine.getStatusCode()).thenReturn(200); |
| 203 | + TelemetryResponse response = new TelemetryResponse().setNumSuccess(1L).setNumProtoSuccess(1L); |
| 204 | + when(mockHttpResponse.getEntity()) |
| 205 | + .thenReturn(new StringEntity(new ObjectMapper().writeValueAsString(response))); |
| 206 | + |
| 207 | + // Set up a client with 3 second flush interval and batch size of 2 |
| 208 | + String jdbcUrl = |
| 209 | + "jdbc:databricks://adb-20.azuredatabricks.net:4423/default;transportMode=http;ssl=1;AuthMech=3;httpPath=/sql/1.0/warehouses/ghgjhgj;UserAgentEntry=MyApp;EnableTelemetry=1;TelemetryBatchSize=2;TelemetryFlushInterval=3000"; |
| 210 | + IDatabricksConnectionContext context = |
| 211 | + DatabricksConnectionContext.parse(jdbcUrl, new Properties()); |
| 212 | + executor = MoreExecutors.newDirectExecutorService(); |
| 213 | + client = new TelemetryClient(context, executor); |
| 214 | + |
| 215 | + // Add events to trigger batch size flush |
| 216 | + client.exportEvent(new TelemetryFrontendLog().setFrontendLogEventId("event1")); |
| 217 | + client.exportEvent( |
| 218 | + new TelemetryFrontendLog() |
| 219 | + .setFrontendLogEventId("event2")); // This should trigger flush due to batch size |
| 220 | + |
| 221 | + // Wait 2 seconds (less than the flush interval) |
| 222 | + Thread.sleep(2000); |
| 223 | + |
| 224 | + // Add another event |
| 225 | + client.exportEvent(new TelemetryFrontendLog().setFrontendLogEventId("event3")); |
| 226 | + |
| 227 | + // Verify it's still in the batch (shouldn't have been flushed yet since timer was reset) |
| 228 | + assertEquals(1, client.getCurrentSize()); |
| 229 | + |
| 230 | + // Wait another 2 seconds (still less than full interval from last flush) |
| 231 | + Thread.sleep(2000); |
| 232 | + |
| 233 | + // Verify it's still not flushed |
| 234 | + assertEquals(1, client.getCurrentSize()); |
| 235 | + |
| 236 | + } finally { |
| 237 | + // Clean up resources |
| 238 | + if (client != null) { |
| 239 | + client.close(); |
| 240 | + } |
| 241 | + if (executor != null) { |
| 242 | + executor.shutdown(); |
| 243 | + // Wait for any pending tasks to complete |
| 244 | + if (!executor.awaitTermination(5, TimeUnit.SECONDS)) { |
| 245 | + executor.shutdownNow(); |
| 246 | + } |
| 247 | + } |
| 248 | + // Verify mocks were properly used |
| 249 | + verify(mockHttpClient, atLeastOnce()).execute(any()); |
| 250 | + verify(mockHttpResponse, atLeastOnce()).getStatusLine(); |
| 251 | + verify(mockStatusLine, atLeastOnce()).getStatusCode(); |
| 252 | + } |
| 253 | + } |
142 | 254 | } |
0 commit comments