SlideShare une entreprise Scribd logo
1  sur  92
Télécharger pour lire hors ligne
StoreDataLoadingMadeEasy-ish
Mike Nakhimovich - NY Times
We ❤Making Apps
We ❤Open Source
Why?Open Source Makes Life Easier
Networking is easier:
HTTPURLCONNECTION
Volley
Retrofit/ Okhttp
Storage is Easier
SharedPreferences
Firebase
Realm
SqlBrite/SqlDelight
Parsing is Easier
JSONObject
Jackson
Gson
Moshi
Fetching, Persisting &
Parsing datahas become
easy
What's NOT Easy?
DATALOADINGEveryone does itdifferently
Whatis DataLoading?
TheActofgetting
datafroman external
systemtoauser'sscreen
Loading is
complicated
Rotation Handling isa special
snowflake
NewYorkTimes builtStoreto
simplifydataloading
github.com/NYTimes/store
OUR GOALS
Datashould survive
configuration changes
agnostic ofwhere itcomes from or
howitis needed
Activitiesand
presenters should
stopretaining MBs
ofdata
Offline as configuration
Cachingas standard,
notan exception
API should be
simple enough for
an internto use,yet
robust enough
for everydataload.
Howdowework
with DataatNY
Times?
80% case:
Need data, don'tcare
iffresh or cached
Need fresh data
background
updates &
pull to refresh
Requests needto be
async & reactive
Datais dependenton
each other,
DataLoading should
betoo
Performance is
importantNewcalls should hook into in flight
responses
Parsing should be
done efficientlyand
minimallyParse onceand cachethe resultfor future calls
Let's Use Repository
PatternBy creating reactiveand persistent
DataStores
Repository Pattern
Separatethe logicthatretrievesthe
dataand maps ittothe [view] model
fromthe [view] logicthatacts onthe
model.
The repositorymediates betweenthe
datalayerandthe [view] layer ofthe
application.
WhyRepository?
Maximizetheamountof
codethatcan betested
withautomation by
isolatingthe datalayer
Why
Repository?
Makes iteasierto have
multiple devsworking on
same feature
Why
Repository?
Datasource from many
locationswillbe centrally
managedwith consistent
access rulesand logic
Our Implementation
https://github.com/NYTimes/Store
WhatisaStore?
Aclassthatmanagesthe
fetching, parsing,and
storage ofaspecific data
model
Tell a Store:
Whatto fetch
Tell a Store:
Whatto fetch
Whereto cache
Tell a Store:
Whatto fetch
Whereto cache
Howto parse
Tell a Store:
Whatto fetch
Whereto cache
Howto parse
The Store handles flow
Storesare Observable
Observable<T> get( V key);
Observable<T> fetch(V key)
Observable<T> stream()
void clear(V key)
Let's see howstores
helped usachieve
our goalsthrougha
PizzaExample
Getis for Handling our 80% Use Case
public final class PizzaActivity {
Store<Pizza, String> pizzaStore;
void onCreate() {
store.get("cheese")
.subscribe(pizza ->.show(pizza));
}
}
Howdoes itflow?
On Configuration Change
You onlyneedto Save/Restoreyour !to get
your cached "
public final class PizzaActivity {
void onRecreate(String topping) {
store.get(topping)
.subscribe(pizza ->.show(pizza));
}
}
Please do notserializeaPizza
Itwould beverymessy
Whatwe gain?:Fragments/Presenters don'tneedto be
retained
NoTransactionTooLargeExceptions
Onlykeys needto be Parcelable
Efficiencyis Important:
for(i=0;i<20;i++){
store.get(topping)
.subscribe(pizza -> getView()
.setData(pizza));
}
ManyconcurrentGetrequestswillstillonly
hitnetwork once
Fetching NewDatapublic class PizzaPresenter {
Store<Pizza, String> store;
void onPTR() {
store.fetch("cheese")
.subscribe(pizza ->
getView().setData(pizza));
}
}
Howdoes Store routethe request?
Fetchalsothrottles multiple requestsand
broadcastresult
Stream listens for events
public class PizzaBar {
Store<Pizza, String> store;
void showPizzaDone() {
store.stream()
.subscribe(pizza ->
getView().showSnackBar(pizza));
}
}
How do We build a
Store?
By implementing interfaces
Interfaces
Fetcher<Raw, Key>{
Observable<Raw> fetch(Key key);
}
Persister<Raw, Key>{}
Observable<Raw> read(Key key);
Observable<Boolean> write(Key key, Raw raw);
}
Parser<Raw, Parsed> extends Func1<Raw, Parsed>{
Parsed call(Raw raw);
}
Fetcher defines how a Store will get new data
Fetcher<Pizza,String> pizzaFetcher =
new Fetcher<Pizza, String>() {
public Observable<Pizza> fetch(String topping) {
return pizzaSource.fetch(topping);
};
Becoming Observable
Fetcher<Pizza,String> pizzaFetcher =
topping ->
Observable.fromCallable(() -> client.fetch(topping));
Parsers helpwith
Fetchersthatdon't
returnViewModels
Some ParsersTransform
Parser<Pizza, PizzaBox> boxParser = new Parser<>() {
public PizzaBox call(Pizza pizza) {
return new PizzaBox(pizza);
}
};
Others read Streams
Parser<BufferedSource, Pizza> parser = source -> {
InputStreamReader reader =
new InputStreamReader(source.inputStream());
return gson.fromJson(reader, Pizza.class);
}
MiddleWare is forthe commonJSON cases
Parser<BufferedSource, Pizza> parser
= GsonParserFactory.createSourceParser(gson,Pizza.class)
Parser<Reader, Pizza> parser
= GsonParserFactory.createReaderParser(gson,Pizza.class)
Parser<String, Pizza> parser
= GsonParserFactory.createStringParser(gson,Pizza.class)
'com.nytimes.android:middleware:CurrentVersion'
'com.nytimes.android:middleware:jackson:CurrentVersion'
'com.nytimes.android:middleware-moshi:CurrentVersion'
Data FlowwithaParser
Adding Offline with Persisters
File System Record Persister
FileSystemRecordPersister.create(
fileSystem,key -> "pizza"+key, 1, TimeUnit.DAYS);
File System is KISS storage
interface FileSystem {
BufferedSource read(String var) throws FileNotFoundException;
void write(String path, BufferedSource source) throws IOException;
void delete(String path) throws IOException;
}
compile 'com.nytimes.android:filesystem:CurrentVersion'
Don'tlike our persisters?
No Problem! You
can implement your
own
Persister interfaces
Persister<Raw, Key> {
Observable<Raw> read(Key key);
Observable<Boolean> write(Key key, Raw raw);
}
Clearable<Key> {
void clear(Key key);
}
RecordProvider<Key> {
RecordState getRecordState( Key key);
DataFlowwithaPersister
We have our components!
Let's buildand openastore
MultiParser
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
Store Builder
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
StoreBuilder<String,BufferedSource,Pizza> parsedWithKey()
Add Our Parser
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
StoreBuilder<String,BufferedSource,Pizza> parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
NowOur Persister
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
StoreBuilder<String,BufferedSource,Pizza> parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.persister( FileSystemRecordPersister.create( fileSystem,
key -> "prefix"+key, 1, TimeUnit.DAYS))
And Our Parsers
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
StoreBuilder<String,BufferedSource,Pizza> parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.persister( FileSystemRecordPersister.create( fileSystem,
key -> "prefix"+key, 1, TimeUnit.DAYS))
.parsers(parsers)
Timeto OpenaStore
List<Parser> parsers=new ArrayList<>();
parsers.add(boxParser);
parsers.add(GsonParserFactory.createSourceParser(gson, Pizza.class));
Store<Pizza, String> pizzaStore =
StoreBuilder<String,BufferedSource,Pizza> parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.persister( FileSystemRecordPersister.create( fileSystem,
key -> "prefix"+key, 1, TimeUnit.DAYS))
.parsers(parsers)
.open();
Configuring caches
Configuring MemoryPolicy
StoreBuilder
.<String, BufferedSource, Pizza>parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.memoryPolicy(MemoryPolicy
.builder()
.setMemorySize(10)
.setExpireAfter(24)
.setExpireAfterTimeUnit(HOURS)
.build())
.open()
Refresh On Stale - BackFillingthe Cache
Store<Pizza, String> pizzaStore = StoreBuilder
.<String, BufferedSource, Pizza>parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.parsers(parsers)
.persister(persister)
.refreshOnStale()
.open();
Network Before Stales Policy
Store<Pizza, String> pizzaStore = StoreBuilder
.<String, BufferedSource, Pizza>parsedWithKey()
.fetcher(topping -> pizzaSource.fetch(topping))
.parsers(parsers)
.persister(persister)
.networkBeforeStale()
.open();
Stores inthewild
Intern Project: BestSellers List
public interface Api {
@GET
Observable<BufferedSource>
getBooks(@Path("category") String category);
@Provides
@Singleton
Store<Books, BarCode> provideBooks(FileSystem fileSystem,
Gson gson, Api api) {
return StoreBuilder.<BarCode, BufferedSource, Books>
parsedWithKey()
.fetcher(category -> api.getBooks(category))
.persister(SourcePersisterFactory.create(fileSystem))
.parser(GsonParserFactory.createSourceParser(gson, Books.class))
.open();
}
public class BookActivity{
...
onCreate(...){
bookStore
.get(category)
.subscribe();
}
Howdo books getupdated?
public class BackgroundUpdater{
...
bookStore
.fresh(category)
.subscribe();
}
DataAvailablewhen screen needs it
UI calls get, background services call fresh
DependentCalls
Simple case Using RxJavaOperators
MapStore resulttoanother Store Result
public Observable<SectionFront> getSectionFront(@NonNull final String name) {
return feedStore.get()
.map(latestFeed -> latestFeed.getSectionOrBlog(name))
.flatMap(section -> sfStore.get(SectionFrontId.of(section)));
}
More Complicated Example
Video Store Returns singlevideos,
PlaylistStore returns playlist,
Howdowe combine?
Relationships by overriding
Get/Fetch
Step1: CreateVideo Store
Store<Video, Long> provideVideoStore(VideoFetcher fetcher,
Gson gson) {
return StoreBuilder.<Long, BufferedSource, Video>parsedWithKey()
.fetcher(fetcher)
.parser(GsonParserFactory
.createSourceParser(gson, Video.class))
.open();
}
Step 2: Create PlaylistStore
public class VideoPlaylistStore extends RealStore<Playlist, Long> {
final Store<CherryVideoEntity, Long> videoStore;
public VideoPlaylistStore(@NonNull PlaylistFetcher fetcher,
@NonNull Store<CherryVideoEntity, Long> videoStore,
@NonNull Gson gson) {
super(fetcher, NoopPersister.create(),
GsonParserFactory.createSourceParser(gson, Playlist.class));
this.videoStore = videoStore;
}
Step 3: Override store.get()
public class VideoPlaylistStore extends RealStore<Playlist, Long> {
final Store<CherryVideoEntity, Long> videoStore;
@Override
public Observable<Playlist> get(Long playlistId) {
return super.get(playlistId)
.flatMap(playlist ->
from(playlist.videos())
.concatMap(video -> videoStore.get(video.id()))
.toList()
.map(videos ->
builder().from(playlist)
.videos(videos)
.build()));
}
Listening for changes
Step1: Subscribeto Store, Filterwhatyou need
sectionFrontStore.subscribeUpdates()
.observeOn(scheduler)
.subscribeOn(Schedulers.io())
.filter(this::sectionIsInView)
.subscribe(this::handleSectionChange);
Step2: Kick offafresh requesttothatstore
public Observable<SectionFront> refreshAll(final String sectionName) {
return feedStore.get()
.flatMapIterable(this::updatedSections)
.map(section->sectionFrontStore.fetch(section))
latestFeed -> fetch(latestFeed.changedSections));
}
Bonus: Howwe made Store
RxJavaforAPIand FunctionalNiceties
public Observable<Parsed> get(@Nonnull final Key key) {
return Observable.concat(
cache(key),
fetch(key)
).take(1);
}
public Observable<Parsed> getRefreshing(@Nonnull final Key key) {
return get(key)
.compose(repeatOnClear(refreshSubject, key));
}
GuavaCaches For MemoryCache
memCache = CacheBuilder
.newBuilder()
.maximumSize(maxSize())
.expireAfterWrite(expireAfter(),timeUnit())
.build();
In FlightThrottlerToo
inflighter.get(key, new Callable<Observable<Parsed>>() {
public Observable<Parsed> call() {
return response(key);
}
})
compile 'com.nytimes.android:cache:CurrentVersion'
Why GuavaCaches?
Theywillblockacrossthreads saving precious MBs ofdownloads
when making same requests in parallel
FileSystem:
Builtusing OKIOtoallowstreaming
from Networkto disk & diskto parser
On Fresh InstallNYTimesappsuccessfullydownloadsand caches
dozens ofmbs ofdata
Would love
contributions &
feedback!thanks for listening

Contenu connexe

Tendances

Appengine Java Night #2b
Appengine Java Night #2bAppengine Java Night #2b
Appengine Java Night #2b
Shinichi Ogawa
 
Appengine Java Night #2a
Appengine Java Night #2aAppengine Java Night #2a
Appengine Java Night #2a
Shinichi Ogawa
 
Enterprise Guice 20090217 Bejug
Enterprise Guice 20090217 BejugEnterprise Guice 20090217 Bejug
Enterprise Guice 20090217 Bejug
robbiev
 

Tendances (20)

Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech TalkContract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux Saga
 
Appengine Java Night #2b
Appengine Java Night #2bAppengine Java Night #2b
Appengine Java Night #2b
 
Appengine Java Night #2a
Appengine Java Night #2aAppengine Java Night #2a
Appengine Java Night #2a
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
 
#ajn3.lt.marblejenka
#ajn3.lt.marblejenka#ajn3.lt.marblejenka
#ajn3.lt.marblejenka
 
[Srijan Wednesday Webinar] Rails 5: What's in It for Me?
[Srijan Wednesday Webinar] Rails 5: What's in It for Me?[Srijan Wednesday Webinar] Rails 5: What's in It for Me?
[Srijan Wednesday Webinar] Rails 5: What's in It for Me?
 
Retrofit
RetrofitRetrofit
Retrofit
 
Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to MissJava Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + Angular
 
Android getting started
Android getting startedAndroid getting started
Android getting started
 
Durable functions
Durable functionsDurable functions
Durable functions
 
iOS Keychain by 흰, 민디
iOS Keychain by 흰, 민디iOS Keychain by 흰, 민디
iOS Keychain by 흰, 민디
 
Enterprise Guice 20090217 Bejug
Enterprise Guice 20090217 BejugEnterprise Guice 20090217 Bejug
Enterprise Guice 20090217 Bejug
 
Android httpclient php_mysql
Android httpclient php_mysqlAndroid httpclient php_mysql
Android httpclient php_mysql
 
第一次用Parse就深入淺出
第一次用Parse就深入淺出第一次用Parse就深入淺出
第一次用Parse就深入淺出
 
Parse Advanced
Parse AdvancedParse Advanced
Parse Advanced
 
Dependency rejection and TDD without Mocks
Dependency rejection and TDD without MocksDependency rejection and TDD without Mocks
Dependency rejection and TDD without Mocks
 
Using Java to interact with Firebase in Android
Using Java to interact with Firebase in AndroidUsing Java to interact with Firebase in Android
Using Java to interact with Firebase in Android
 
Android Libs - Retrofit
Android Libs - RetrofitAndroid Libs - Retrofit
Android Libs - Retrofit
 

Similaire à Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017

Ft10 de smet
Ft10 de smetFt10 de smet
Ft10 de smet
nkaluva
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
ShriKant Vashishtha
 
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Ingesting streaming data for analysis in apache ignite (stream sets theme)Ingesting streaming data for analysis in apache ignite (stream sets theme)
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Tom Diederich
 

Similaire à Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017 (20)

Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTech
 
하이퍼커넥트 데이터 팀이 데이터 증가에 대처해온 기록
하이퍼커넥트 데이터 팀이 데이터 증가에 대처해온 기록하이퍼커넥트 데이터 팀이 데이터 증가에 대처해온 기록
하이퍼커넥트 데이터 팀이 데이터 증가에 대처해온 기록
 
twMVC#46 一探 C# 11 與 .NET 7 的神奇
twMVC#46 一探 C# 11 與 .NET 7 的神奇twMVC#46 一探 C# 11 與 .NET 7 的神奇
twMVC#46 一探 C# 11 與 .NET 7 的神奇
 
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVCConstruindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
 
Change tracking
Change trackingChange tracking
Change tracking
 
Getting Started with Real-Time Analytics
Getting Started with Real-Time AnalyticsGetting Started with Real-Time Analytics
Getting Started with Real-Time Analytics
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
 
Wcf data services
Wcf data servicesWcf data services
Wcf data services
 
Bringing JAMStack to the Enterprise
Bringing JAMStack to the EnterpriseBringing JAMStack to the Enterprise
Bringing JAMStack to the Enterprise
 
Ft10 de smet
Ft10 de smetFt10 de smet
Ft10 de smet
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
meetstore5.pdf
meetstore5.pdfmeetstore5.pdf
meetstore5.pdf
 
Bootiful Development with Spring Boot and React - UberConf 2018
Bootiful Development with Spring Boot and React - UberConf 2018Bootiful Development with Spring Boot and React - UberConf 2018
Bootiful Development with Spring Boot and React - UberConf 2018
 
Bootiful Development with Spring Boot and React - RWX 2017
Bootiful Development with Spring Boot and React - RWX 2017Bootiful Development with Spring Boot and React - RWX 2017
Bootiful Development with Spring Boot and React - RWX 2017
 
Ingesting streaming data for analysis in apache ignite (stream sets theme)
Ingesting streaming data for analysis in apache ignite (stream sets theme)Ingesting streaming data for analysis in apache ignite (stream sets theme)
Ingesting streaming data for analysis in apache ignite (stream sets theme)
 
2015 09-02 - transaction log prototype
2015 09-02 - transaction log prototype2015 09-02 - transaction log prototype
2015 09-02 - transaction log prototype
 
Marvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey BuzdinMarvel of Annotation Preprocessing in Java by Alexey Buzdin
Marvel of Annotation Preprocessing in Java by Alexey Buzdin
 
Building a Real-Time Feature Store at iFood
Building a Real-Time Feature Store at iFoodBuilding a Real-Time Feature Store at iFood
Building a Real-Time Feature Store at iFood
 
Spicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QASpicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QA
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Dernier (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017