/* * Copyright © 2015 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.examples.profiles; import co.cask.cdap.api.annotation.ProcessInput; import co.cask.cdap.api.annotation.UseDataSet; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.api.dataset.lib.KeyValueTable; import co.cask.cdap.api.dataset.table.Get; import co.cask.cdap.api.dataset.table.Put; import co.cask.cdap.api.dataset.table.Table; import co.cask.cdap.api.flow.AbstractFlow; import co.cask.cdap.api.flow.flowlet.AbstractFlowlet; import co.cask.cdap.api.flow.flowlet.OutputEmitter; import co.cask.cdap.api.flow.flowlet.StreamEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Reads click events from a stream, counts clicks per URL, and records user's last activity in their profiles. */ public class ActivityFlow extends AbstractFlow { private static final Logger LOG = LoggerFactory.getLogger(ActivityFlow.class); @Override protected void configure() { setName("ActivityFlow"); setDescription("Reads click events from a stream, counts clicks per URL, and records user activity."); addFlowlet("reader", new EventReader()); addFlowlet("counter", new Counter()); addFlowlet("updater", new Updater()); connectStream("events", "reader"); connect("reader", "counter"); connect("reader", "updater"); } private class EventReader extends AbstractFlowlet { private OutputEmitter<Event> out; @ProcessInput public void process(StreamEvent streamEvent) { try { out.emit(Event.fromJson(streamEvent.getBody())); } catch (Exception e) { LOG.debug("Problem decoding event: {}", Bytes.toString(streamEvent.getBody()), e); } } } private class Counter extends AbstractFlowlet { @UseDataSet("counters") private KeyValueTable counters; @ProcessInput public void process(Event event) { counters.increment(Bytes.toBytes(event.getUrl()), 1L); } } private class Updater extends AbstractFlowlet { @UseDataSet("profiles") private Table profiles; @ProcessInput public void process(Event event) { String id = event.getUserId(); if (profiles.get(new Get(id, "id")).isEmpty()) { LOG.debug("Received event for unknown user id {}.", id); return; } profiles.put(new Put(id, "active", event.getTime())); } } }